Koden som skrevs blev inte ens sparad för mig. Det verkar som några problem. Osäker på om detta är den faktiska koden eller om några saker försvann i kopieringen. Men baserat på vad du har:
En stor sak är att du aldrig ansluter till databasen i din kod med connection.connect().
Koden du vill köra när du väl är ansluten ska finnas inuti connection.connect()-återuppringningen. t.ex.
connection.connect(function (err, empty) {
if (err)
throw new Error ('Panic');
// if no error, we are off to the races...
}
Men även om du snabbt refaktorerar din kod för att linda dina sista rader inuti som får anslutningsåteruppringning, kommer du fortfarande att ha problem, eftersom du förstör anslutningen innan de olika SQL-anropen görs, så du kommer att vilja flytta kod till någon form av slutlig återuppringning.
Även efter att du har gjort det kommer du fortfarande att ha en tom fil, eftersom du anropar save_backup från din "SHOW TABLES"-återuppringning snarare än efter att du faktiskt har fyllt i den via den inre återuppringningen där du får CREATE TABLE-satsen och fyller i backup-egenskap.
Detta är den minimala omskrivningen av din kod som kommer att göra vad du har för avsikt. En viktig sak att notera är "räknaren" som hanterar när du ska skriva filen och stänga anslutningen. Jag skulle göra andra ändringar om det var min, inklusive:
- Använder "jag" istället för "mig"
- Användning av en numerisk för loop snarare än för (... i ...) syntax
- Att ha mina egna återuppringningar faller på nodkonventionen för (fel, grejer)
- En mer väsentlig förändring är att jag skulle skriva om detta för att använda löften, eftersom det kan bespara dig lite sorg med den förvirring som är inneboende med djupt kapslade återuppringningar. Jag personligen gillar Q-biblioteket, men det finns flera alternativ här.
Hoppas detta hjälpte.
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){;});
});
Uppdatering:Om du är nyfiken, här är en starkt kommenterad implementering med löften. Observera att utan kommentarerna som förklarar Q-löftets biblioteksfunktioner, är det något kortare än originalversionen och erbjuder även mer omfattande felhantering.
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');