2014-07-21 36 views
1

我正在尝试使用promise来调用getLoginState,然后存储该值,以便稍后使用它。为什么这个嵌套promise,然后在承诺的方法之前执行?

我想知道为什么在下面的代码块中,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(); 
}; 
+0

有一点需要注意(我不能确定这是否是代码中的问题)是,在为其赋值之前,您可能会引用'getLoginState'。这就是为什么我不使用'var getLoginState = function(){'定义一个函数的形式,除非它是必需的。如果你使用'function getLoginState(){'来代替它,它会被挂起并且总是被定义,然后才能使用它。 – jfriend00

+0

@ jfriend00承诺保证在异步循环的某些未来时间内执行并且从不同步 - 因此在这种情况下它不是问题。 –

回答

3

在承诺的流量控制就像同步代码:

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

承诺的工作方式 - 是等待他们。在一个NodeJS风格的“errback”回调中调用nfcall。为了让你的代码工作,你需要从getLoginState回报,然后不要使用nfcall,因为该方法已返回一个承诺:

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 

我想强调的是,这可能写得更好,没有什么理由在这里嵌套而不是链接,并且连接应该在承诺中完成 - 上面的代码与您的代码的作用最接近。

+0

真棒!非常感谢:)我试图在没有嵌套的情况下写得更好:q.nfcall(...) .then(function(results){ console.log(“select:”+ results [0] [0]); })。然后(返回getLoginState(),函数(状态)console.log(“gotLoginState:”+ state); })。catch(function(error){ console.error(“promise error:”+错误); })。done(); – Omnipotence

相关问题