【问题标题】:Losing Variable Scope失去可变范围
【发布时间】:2014-05-08 08:53:53
【问题描述】:

所以,一旦我解决了我之前问题的承诺问题,我尝试在登录时从数据库中获取玩家帐户 X、Y 坐标(这样它们就不会放在 1,1 上,而是放在最后一个跟踪坐标)

经过一番调试,我得出了这个结论:

var x; //note I also tried to define these directly above the getX/Y() and it didn't work
var y;
return con.getConnectionAsync().then(function(connection) {
    return connection.queryAsync('SELECT password,id FROM player WHERE name='+mysql.escape(req.body.user))
        .spread(function(rows, fields) {
        if (hash.verify(req.body.pass,rows[0].password)) {
            req.session.loggedIn = true;
            req.session.user = rows[0].id;
            getX(rows[0].id,con,mysql).then(function(data) {
                x = data;
            });
            getY(rows[0].id,con,mysql).then(function(data) {
                y = data;
            });
            console.log(x,y,"line77");
            ref = new P(rows[0].id,x,y);
            res.send({
                "msg":"You have logged in!",
                "flag":false,
                "title":": Logged In"
            });
            return ref;
        } else {
            res.send({
                "msg":"Your username and or password was incorrect.",
                "flag":true,
                "title":": Login Failed"
            });
        }
    }).finally(function() {
        connection.release();
    });
});

这就是整个功能——以防万一缺少某些范围。但这里是麻烦线:

getX(rows[0].id,con,mysql).then(function(data) {
    x = data; //x logs the return 7 from the db
});
getY(rows[0].id,con,mysql).then(function(data) {
    y = data; //y logs 45 from the db
});
console.log(x,y,"line77"); //logs "undefined undefined line77"
ref = new P(rows[0].id,x,y);

我的印象是Promise 会在我的查询完成之前解决这个函数触发问题,但我想不会。

为什么我的函数在设置 X、Y 变量之前返回?

注意:下一步是将我的关注点与函数分开,所以请忽略我在传递conmysql 就像在比赛中的接力棒一样。谢谢!

【问题讨论】:

    标签: javascript mysql node.js promise bluebird


    【解决方案1】:

    为什么我的函数在设置 X、Y 变量之前返回?

    Because JavaScript I/O is asynchronous

    如果你想等待两个承诺 - 你需要挂钩承诺的完成。幸运的是,通过 Promise.allPromise.spread,Promise 让你的操作变得超级简单。

    Promise.all(getX(rows[0].id,con,mysql),getY(rows[0].id,con,mysql)).spread(function(x,y){
         console.log(x,y);//should work;
    });
    

    【讨论】:

      【解决方案2】:

      Promise 不会改变语言,它只是一个库。它不能改变函数返回的工作方式。但是,你想要这样的东西吗:

      return con.getConnectionAsync().then(function(connection) {
          var x;
          var y;
          return connection.queryAsync('SELECT password,id FROM player WHERE name='+mysql.escape(req.body.user))
              .spread(function(rows, fields) {
              if (hash.verify(req.body.pass,rows[0].password)) {
                  req.session.loggedIn = true;
                  req.session.user = rows[0].id;
                  ref = new P(rows[0].id,x,y);
                  res.send({
                      "msg":"You have logged in!",
                      "flag":false,
                      "title":": Logged In"
                  });
                  return Promise.all([
                      getX(rows[0].id,con,mysql),
                      getY(rows[0].id,con,mysql)
                  ]).then(function(xy) {
                      x = xy[0];
                      y = xy[1];
                  }).return(ref);
              } else {
                  // Should probably throw a LoginError here or something
                  // because if we get here, we don't define x and y
                  // and that will require an annoying check later
                  res.send({
                      "msg":"Your username and or password was incorrect.",
                      "flag":true,
                      "title":": Login Failed"
                  });
              }
          }).then(function() {
              // If the login succeeded x and y are defined here.
              // However, in the else branch you don't define
              // x and y so you will need to check here.
              // Had you thrown an error in the else branch
              // you would know that x and y are always defined here.
              use(x, y);
          }).finally(function() {
              connection.release();
          });
      });
      

      【讨论】:

        【解决方案3】:

        函数getXgetY 是异步函数。 Promise 解决了嵌套匿名函数的问题,但它不会使函数同步和阻塞。

        所以xy 在您创建ref 对象并返回此对象时没有设置。

        试试这样的:

        getX(rows[0].id,con,mysql).then(function(data) {
            x = data; //x logs the return 7 from the db
            getY(rows[0].id,con,mysql).then(function(data) {
                y = data; //y logs 45 from the db
                console.log(x,y,"line77"); //logs "undefined undefined line77"
                ref = new P(rows[0].id,x,y);
            });
        });
        

        另外,由于您的整个函数是异步的,您必须使用回调或返回一个 Promise,您可以在其中访问 ref Object。

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多