De code zoals geschreven kwam voor mij niet eens bij het opslaan van bestanden. Er lijken een paar problemen. Ik weet niet zeker of dit de daadwerkelijke code is of dat er dingen verloren zijn gegaan bij het kopiëren en plakken. Maar op basis van wat je hebt:
Een grote is dat je nooit verbinding maakt met de database in je code met connection.connect().
De code die u wilt uitvoeren zodra u bent verbonden, moet zich binnen de callback van connection.connect() bevinden. bijv.
connection.connect(function (err, empty) {
if (err)
throw new Error ('Panic');
// if no error, we are off to the races...
}
Maar zelfs als u uw code snel refactoreert om uw laatste regels binnen die get-connection callback te laten vallen, zult u nog steeds problemen hebben, omdat u de verbinding vernietigt voordat de verschillende SQL-aanroepen worden gedaan, dus u wilt de code in een soort laatste terugroepactie.
Zelfs nadat je dat hebt gedaan, heb je nog steeds een leeg bestand, omdat je save_backup aanroept vanuit je 'SHOW TABLES'-callback in plaats van nadat je het daadwerkelijk hebt ingevuld via de innerlijke callback waar je de CREATE TABLE-instructie krijgt en de back-upeigenschap.
Dit is het minimale herschrijven van uw code die zal doen wat u van plan bent. Een belangrijk ding om op te merken is de "teller" die beheert wanneer het bestand moet worden geschreven en de verbinding moet worden gesloten. Ik zou andere wijzigingen aanbrengen als het van mij was, waaronder:
- Gebruik 'zelf' in plaats van 'ik'
- Een numerieke for-lus gebruiken in plaats van de for (... in ...) syntaxis
- Het hebben van mijn eigen callbacks valt onder de knooppuntconventie van (err, stuff)
- Een meer substantiële verandering is dat ik dit zou herschrijven om beloften te gebruiken, omdat dit je wat verdriet kan besparen met de verwarring die inherent is aan diep genestelde terugbelverzoeken. Ik hou persoonlijk van de Q-bibliotheek, maar er zijn hier verschillende opties.
Ik hoop dat dit heeft geholpen.
var mysql_backup = function(){
this.backup = '';
this.mysql = require('mysql');
this.init = function(){
this.connection = this.mysql.createConnection({
user : 'root',
password : 'root',
database : 'test'
});
};
this.query = function(sql, callback) {
this.connection.query(sql, function (error, results, fields) {
if (error) {
throw error;
}
if (results.length > 0) {
callback(results);
}
});
};
this.get_tables = function(callback){
var counter = 0;
var me = this;
this.query('SHOW TABLES',
function(tables) {
for (table in tables){
counter++;
me.query(
'SHOW CREATE TABLE ' + tables[table].Tables_in_mvc,
function(r){
for (t in r) {
me.backup += "DROP TABLE " + r[t].Table + "\n\n";
me.backup += r[t]["Create Table"] + "\n\n";
}
counter--;
if (counter === 0){
me.save_backup();
me.connection.destroy();
}
}
)
}
});
};
this.save_backup = function(){
var fs = require('fs');
fs.writeFile("./backup_test.txt", this.backup, function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
}
};
var db = new mysql_backup;
db.init();
db.connection.connect(function (err){
if (err) console.log(err);
db.get_tables(function(x){;});
});
Update:als je nieuwsgierig bent, hier is een zwaar becommentarieerde implementatie met beloften. Merk op dat zonder de opmerkingen die de functies van de Q-beloftebibliotheek uitleggen, deze iets korter is dan de originele versie en ook een uitgebreidere foutafhandeling biedt.
var MysqlBackup = function(connectionInfo, filename){
var Q = require('q');
var self = this;
this.backup = '';
// my personal preference is to simply require() inline if I am only
// going to use something a single time. I am certain some will find
// this a terrible practice
this.connection = require('mysql').createConnection(connectionInfo);
function getTables(){
// return a promise from invoking the node-style 'query' method
// of self.connection with parameter 'SHOW TABLES'.
return Q.ninvoke(self.connection,'query', 'SHOW TABLES');
};
function doTableEntries(theResults){
// note that because promises only pass a single parameter around,
// if the 'denodeify-ed' callback has more than two parameters (the
// first being the err param), the parameters will be stuffed into
// an array. In this case, the content of the 'fields' param of the
// mysql callback is in theResults[1]
var tables = theResults[0];
// create an array of promises resulting from another Q.ninvoke()
// query call, chained to .then(). Note that then() expects a function,
// so recordEntry() in fact builds and returns a new one-off function
// for actually recording the entry (see recordEntry() impl. below)
var tableDefinitionGetters = [];
for (var i = 0; i < tables.length ; i++){
// I noticed in your original code that your Tables_in_[] did not
// match your connection details ('mvc' vs 'test'), but the below
// should work and is a more generalized solution
var tableName = tables[i]['Tables_in_'+connectionInfo.database];
tableDefinitionGetters.push(Q.ninvoke(self.connection, 'query', 'SHOW CREATE TABLE ' + tableName)
.then(recordEntry(tableName)) );
}
// now that you have an array of promises, you can use Q.allSettled
// to return a promise which will be settled (resolved or rejected)
// when all of the promises in the array are settled. Q.all is similar,
// but its promise will be rejected (immediately) if any promise in the
// array is rejected. I tend to use allSettled() in most cases.
return Q.allSettled(tableDefinitionGetters);
};
function recordEntry (tableName){
return function(createTableQryResult){
self.backup += "DROP TABLE " + tableName + "\n\n";
self.backup += createTableQryResult[0][0]["Create Table"] + "\n\n";
};
};
function saveFile(){
// Q.denodeify return a promise-enabled version of a node-style function
// the below is probably excessively terse with its immediate invocation
return (Q.denodeify(require('fs').writeFile))(filename, self.backup);
}
// with the above all done, now you can actually make the magic happen,
// starting with the promise-return Q.ninvoke to connect to the DB
// note that the successive .then()s will be executed iff (if and only
// if) the preceding item resolves successfully, .catch() will get
// executed in the event of any upstream error, and finally() will
// get executed no matter what.
Q.ninvoke(this.connection, 'connect')
.then(getTables)
.then(doTableEntries)
.then(saveFile)
.then( function() {console.log('Success'); } )
.catch( function(err) {console.log('Something went awry', err); } )
.finally( function() {self.connection.destroy(); } );
};
var myConnection = {
host : '127.0.0.1',
user : 'root',
password : 'root',
database : 'test'
};
// I have left this as constructor-based calling approach, but the
// constructor just does it all so I just ignore the return value
new MysqlBackup(myConnection,'./backup_test.txt');