Problemer med koden
Ok, der er mange problemer her, så først til kende.
connection.query('...', function (err, rows) {
connection.release();
if (!err) {
return rows;
} else {
return false;
}
});
Dette vil ikke fungere, fordi du returnerer data til den, der ringer, som er databaseforespørgslen, der kalder dit tilbagekald med err
og rows
og er ligeglad med returværdien af dit tilbagekald.
Det du skal gøre er at kalde en anden funktion eller metode, når du har rækkerne, eller når du ikke har det.
Du ringer til:
var rows = loginM.findUser(req.body, res);
og du forventer at få rækkerne der, men det vil du ikke. Det du får er undefined
og du får det hurtigere, end databaseforespørgslen overhovedet er startet. Det fungerer sådan her:
me.findUser = function(params, res) {
// (1) you save the username in a variable
var username = params.username;
// (2) you pass a function to getConnection method
pool.getConnection(function (err, connection) {
console.log("Connection ");
if (err) {
console.log("ERROR 1 ");
res.send({"code": 100, "status": "Error in connection database"});
return;
}
connection.query('select Id, Name, Password from Users ' +
'where Users.Name = ?', [username], function (err, rows) {
connection.release();
if (!err) {
return rows;
} else {
return false;
}
});
//connection.on('error', function (err) {
// res.send({"code": 100, "status": "Error in connection database"});
// return;
//});
});
// (3) you end a function and implicitly return undefined
}
pool.getConnection
metoden returnerer umiddelbart efter du har sendt en funktion, før forbindelsen til databasen overhovedet er oprettet. Så, efter et stykke tid, kan den funktion, som du har videregivet til den metode, blive kaldt, men det vil vare længe efter, at du allerede har returneret undefined
til koden, der ønskede en værdi i:
var rows = loginM.findUser(req.body, res);
I stedet for at returnere værdier fra tilbagekald, skal du kalde nogle andre funktioner eller metoder fra dem (som nogle tilbagekald, du skal kalde, eller en metode til at løse et løfte).
At returnere en værdi er et synkront koncept og vil ikke fungere for asynkron kode.
Hvordan løfter skal bruges
Nu, hvis din funktion returnerede et løfte :
me.findUser = function(params, res) {
var username = params.username;
return new Promise(function (res, rej) {
pool.getConnection(function (err, connection) {
console.log("Connection ");
if (err) {
rej('db error');
} else {
connection.query('...', [username], function (err, rows) {
connection.release();
if (!err) {
res(rows);
} else {
rej('other error');
}
});
});
});
}
så vil du være i stand til at bruge den i en anden del af din kode på en måde som denne:
app.post('/login/', function(req, res, next) {
var promise = new Promise(function (resolve, reject) {
// rows is a promise now:
var rows = loginM.findUser(req.body, res);
rows.then(function (rowsValue) {
console.log("Success");
resolve(rowsValue);
}).catch(function (err) {
console.log("Failed");
reject(err);
});
});
// ...
Forklaring
Sammenfattende, hvis du kører en asynkron operation - som en databaseforespørgsel - så kan du ikke umiddelbart have værdien sådan:
var value = query();
fordi serveren skulle blokere for at vente på databasen, før den kunne udføre opgaven - og det er hvad der sker på alle sprog med synkron, blokerende I/O (det er derfor du skal have tråde på de sprog, så andre ting kan gjort, mens tråden er blokeret).
I Node kan du enten bruge en tilbagekaldsfunktion, som du overfører til den asynkrone funktion for at blive kaldt, når den har data:
query(function (error, data) {
if (error) {
// we have error
} else {
// we have data
}
});
otherCode();
Eller du kan få et løfte:
var promise = query();
promise.then(function (data) {
// we have data
}).catch(function (error) {
// we have error
});
otherCode();
Men i begge tilfælde otherCode()
vil blive kørt umiddelbart efter registrering af dine tilbagekalds- eller løftehandlere, før forespørgslen har nogen data - det betyder, at ingen blokering skal foretages.
Oversigt
Hele ideen er, at i et asynkront, ikke-blokerende, enkelttrådsmiljø som Node.JS laver man aldrig mere end én ting ad gangen – men man kan vente på mange ting. Men du venter ikke bare på noget og laver ingenting, mens du venter, du planlægger andre ting, venter på flere ting, og til sidst bliver du ringet tilbage, når det er klar.
Faktisk skrev jeg en novelle på Medium for at illustrere det koncept:I/O ikke-sort på planeten Asynchronia256/16 - En novelle løst baseret på usikre fakta .