Il codice come scritto non è nemmeno arrivato a un file di salvataggio per me. Sembra che ci siano alcuni problemi. Non sono sicuro se questo è il codice effettivo o se alcune cose sono andate perse nel copia incolla. Tuttavia, in base a ciò che hai:
Un grosso problema è che non ti connetti mai al database nel tuo codice con connection.connect().
Il codice che vuoi eseguire una volta connesso dovrebbe trovarsi all'interno del callback connection.connect(). es.
connection.connect(function (err, empty) {
if (err)
throw new Error ('Panic');
// if no error, we are off to the races...
}
Tuttavia, anche se esegui rapidamente il refactoring del tuo codice per racchiudere le tue ultime righe all'interno di quella richiamata di connessione, avrai comunque problemi, perché stai distruggendo la connessione prima che vengano effettuate le varie chiamate SQL, quindi ti consigliamo di spostare il codice in una sorta di richiamata finale.
Anche dopo averlo fatto, avrai ancora un file vuoto, perché stai chiamando save_backup dal tuo callback "SHOW TABLES" piuttosto che dopo averlo effettivamente popolato tramite il callback interno dove ottieni l'istruzione CREATE TABLE e popola il proprietà di backup.
Questa è la riscrittura minima del tuo codice che farà ciò che intendi. Una cosa importante da notare è il "contatore" che gestisce quando scrivere il file e chiudere la connessione. Farei altre modifiche se fosse mio, tra cui:
- Utilizzare 'self' invece di 'me'
- Utilizzare un ciclo for numerico anziché la sintassi for (... in ...)
- Avere i miei callback rientra nella convenzione del nodo di (err, roba)
- Un cambiamento più sostanziale è che lo riscriverei per usare le promesse, in quanto ciò può risparmiarti un po' di dolore con la confusione inerente ai callback profondamente nidificati. Personalmente mi piace la libreria Q, ma qui ci sono diverse opzioni.
Spero che questo ha aiutato.
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){;});
});
Aggiornamento:se sei curioso, ecco un'implementazione fortemente commentata che utilizza le promesse. Nota che senza i commenti che spiegano le funzioni della libreria Q promise, è leggermente più breve della versione originale e offre anche una gestione degli errori più completa.
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');