Javascript JS-然后等待承诺

Javascript JS-然后等待承诺,javascript,promise,Javascript,Promise,我知道这是一个常见的话题,但我只想确认我对JS和承诺的理解 下面的代码段失败了,因为then块实际上没有等待上面的代码段完成。也就是说,我没有得到okCheck的最终/正确值 var okCheck = false; User.findOne({publicID: id}, function (err, userInfo) { if ( userInfo.checked.indexOf(id) > -1 ){ okCheck = true; } }

我知道这是一个常见的话题,但我只想确认我对JS和承诺的理解

下面的代码段失败了,因为
then
块实际上没有等待上面的代码段完成。也就是说,我没有得到
okCheck
的最终/正确值

var okCheck = false;

User.findOne({publicID: id}, function (err, userInfo) {
      if ( userInfo.checked.indexOf(id) > -1 ){
        okCheck = true;
      }
})
.then(function() {
      //do some additional stuff using the boolean okCheck
}
所以要解决这个问题——据我所知,我需要使用一个
返回值
——这是正确的吗

var okCheck = false;

User.findOne({publicID: id}, function (err, userInfo) {
      if ( userInfo.checked.indexOf(id) > -1 ){
        okCheck = true;
      }
      return okCheck;
})
.then(function() {
      //do some additional stuff using the boolean okCheck
}
这是正确的吗?也就是说,我是否保证始终拥有okCheck的最终值


谢谢。

这不是它的工作原理,您必须返回承诺才能使用“.then()”

此处“.exec()”返回承诺

据我所知,我需要使用
返回值
-这是否正确

var okCheck = false;

User.findOne({publicID: id}, function (err, userInfo) {
      if ( userInfo.checked.indexOf(id) > -1 ){
        okCheck = true;
      }
      return okCheck;
})
.then(function() {
      //do some additional stuff using the boolean okCheck
}
对。但是
return
ing值不会影响任何与时间相关的内容

关键是,您从
然后
回调返回的
值将是它返回的承诺的解析值,并成为链中下一个回调的参数

您不应该修改异步回调中的外部作用域变量。正确的方法是推迟行动,直到承诺得到解决,而不是“等待”变量值出现:

// no `var` here!
User.findOne({publicID: id}).then(function(userInfo) {
    return userInfo.checked.indexOf(id) > -1;
//  ^^^^^^ return a boolean
}).then(function(okCheck) {
//               ^^^^^^^ receive it here as a parameter
    … // do some additional stuff using it
});
两点:

  • okCheck
    无法在User.findOne的回调或chained.then的回调的上下文之外可靠地使用,因此将其作为外部变量没有任何好处,事实上这样做是不好的做法
  • 您不应该同时尝试使用直接回调和链接的
    then()
    ——它们是可选的
假设这是Mongoose,并且
userInfo.checked.indexOf()
是同步的,您可以编写以下任意一项:

将回调传递给
User.findOne()

User.findOne({publicID: id}, function(err, userInfo) {
    if(err) {
        console.log(err);
    } else {
        if (userInfo.checked.indexOf(id) > -1) {
            // do additional stuff
        } else {
            // do other stuff
        }
    }
});
User.findOne({publicID: id}}).exec().then(function(userInfo) {
    if(userInfo.checked.indexOf(id) > -1) {
        // do additional stuff
    } else {
        // do other stuff
    }
}, function(err) {
    console.log(err);
});
.then()
链接到
用户返回的承诺。findOne().exec()

User.findOne({publicID: id}, function(err, userInfo) {
    if(err) {
        console.log(err);
    } else {
        if (userInfo.checked.indexOf(id) > -1) {
            // do additional stuff
        } else {
            // do other stuff
        }
    }
});
User.findOne({publicID: id}}).exec().then(function(userInfo) {
    if(userInfo.checked.indexOf(id) > -1) {
        // do additional stuff
    } else {
        // do other stuff
    }
}, function(err) {
    console.log(err);
});

注意:即使不是Mongoose,这一点仍然适用。

处理程序中使用的
new Promise()
绝对没有理由。只需在
中返回一个值即可。然后()
handler,这将成为当前承诺的解析值。因此,使用我在问题中的上述代码
return-okCheck
本身就可以了?现在其他人对上述内容的看法如何?对我来说有意义??一点吹毛求疵:您不再需要在外部范围内声明
okCheck
:它可以在内部范围内声明第一个
然后是
处理程序。这也迫使您在第二个
处理程序中从传递的参数而不是从外部作用域中获取结果。
findOne
函数看起来很奇怪:从您的代码来看,它似乎接受回调参数并返回承诺。这两种机制的作用大致相同,您希望函数使用回调或承诺。你确定你叫对了吗?您能否验证您的回调和
then
处理程序是否都被调用(例如,通过在它们内部添加
console.log()
调用)?这很好-我使用了console.log来检查这一点。我认为下面的答案看起来不错-您认为>从答案来看,这个特殊的
findOne
函数是。如果您提到您正在使用的库,那么会更加清楚,这样其他人就不必猜测您的代码正在使用什么函数。;-)
User.findOne()
记录在哪里?如果一个方法接受回调并且是可启用的,那么使用其中一个接口就更正常了,而不是同时使用这两个接口。。。。。谢谢@MattiasBuelens,在我提问之前你可能已经回答了我的问题。