为什么这个嵌套的承诺,然后在承诺的方法之前执行?

我正在尝试使用promise来调用getLoginState,然后存储该值,以便稍后使用它。

我想知道为什么在下面的代码块,q.fcall(getLoginState)的.then里面getLoginState方法之前调用?

var mysql = require('mysql'); var q = require('q'); var login = "tyler"; var connection = mysql.createConnection({ host : 'localhost', user: 'root', password: 'root', port: '3306', database: 'root' }); var gotLoginState; var state; connection.connect(function(err) { if(err != null){ console.log("connection err: "+err); } q.nfcall(connection.query.bind(connection),"SELECT id, password, salt, gender, banned, gm, pin, pic, characterslots, tos FROM accounts WHERE name = ?",[login]) .then(function (results) { console.log("select: "+results[0][0]); // }).then(q.fcall(getLoginState), function () { q.fcall(getLoginState) .then(function() { console.log("gotLoginState: " + state); }).catch(function (error){ console.log("error in inner thing"); }).done(); }).catch(function (error) { console.error("promise error: "+error); }) .done(); }); var accId = 1; var getLoginState = function() { q.nfcall(connection.query.bind(connection), "SELECT loggedin, lastlogin, UNIX_TIMESTAMP(birthday) as birthday FROM accounts WHERE id = ?", [accId]) .then(function (results) { state = results[0][0].loggedin; }).catch(function (error) { console.log("error in chaining: "+error); }).done(); }; 

       

网上收集的解决方案 "为什么这个嵌套的承诺,然后在承诺的方法之前执行?"

承诺中的stream程控制就像同步代码一样工作:

  • 要返回,请使用return关键字。
  • 要发出错误信号,请使用关键字。

承诺的工作方式是等待他们。 nfcallnfcall风格的“errback”callback上被调用。 为了让你的代码工作,你需要从getLoginState返回 ,然后不要使用nfcall因为方法已经返回一个promise:

 var getLoginState = function() { // this should be nodeify probably return q.nfcall(...) // note the `return` statement here .then(function (results) { state = results[0][0].loggedin; // do not mutate state like this }).catch(function (error) { // instead use return values console.log("error in chaining: "+error); // don't suppress errors // logging is not enough }); // don't do `.done` if you want to chain to it }; 

然后在上面的部分:

 // don't use the `.connect` callback, promisify it q.nfcall(...) // promisify that method _once_ in your real code .then(function (results) { console.log("select: "+results[0][0]); // why just the log? return getLoginState() // note this is a regular function call .then(function() { // also note the `return` console.log("gotLoginState: " + state); }).catch(function (error){ console.log("error in inner thing"); }); // no done here, since we chain to it }).catch(function (error) { console.error("promise error: "+error); }).done(); // you only need one `.done` at the end, and only in old // promise libraries 

我想强调的是,这可能会写得更好,没有什么好的理由嵌套在这里,而不是链,连接应该在承诺 – 上面的代码是最接近你的代码的作品。