我对promise的链接如何工作感到困惑,我对promise和js还是很陌生,所以请问。

第三行,return user.findOne({email}).then((user) => {,我只是对如何返回此承诺感到困惑,因为它在.then()内部返回了另一个承诺。

UserSchema.statics.findByCredentials = function(email, password){
  user = this;
  return user.findOne({email}).then((user) => {
      if (!user){
        return Promise.reject();
      }
      return new Promise((resolve, reject) => {
        bcrypt.compare(password, user.password, (err, res) => {
          if (res){
            resolve(user);
          }else{
            reject()
          }
        });
    });

  });
}


Express应用程序中使用的findByCredentials模型方法

app.post("/users/login", (req, res) => {
  var body = _.pick(req.body, ["email", "password"]);
  User.findByCredentials(body.email, body.password).then((user) => {
    res.send(body)
  }).catch((e) => {
    res.send("!");
  })


我刚刚创建的一个简单示例,这部分


  返回plus(1).then((res)=> {
  
  
    返回新的Promise((resolve,reject)=> {
    是我无法理解的问题
  


function plus(a) {
  return new Promise((resolve, reject) => {
    resolve(a + 1);
  });
}

function test() {
  return plus(1).then((res) => {
    console.log(res);
    return new Promise((resolve, reject) => {
      resolve("Test");
    });
  });
}

test().then((res) => {
  console.log(res);
});

最佳答案

正如@Bergi在您的OP的评论中所说,真正的力量或Promises来自于将它们返回到其他thenPromises中。


这使您可以以干净的方式链接Promises。
链接Promise,您在链中的所有操作都必须是Promises。
您的bcrypt.compare函数使用回调来表明已完成,因此您需要将该函数转换为Promise


这很容易做到。只需将回调样式的代码包装在Promise中,然后将resolve封装在回调的result中,或者将reject封装在如果使用err进行调用的情况下。

const comparePassword = (a, b) => {
  return new Promise((resolve, reject) => {
    bcrypt.compare(a, b, (err, result) => {
      // Reject if there was an error
      // - rejection is `return`-ed solely for stopping further execution
      //   of this callback. No other reason for it.
      if (err) return reject(err)

      // Resolve if not.
      resolve(result)
    })
  })
}


...然后我们可以正确地链接:

UserSchema.statics.findByCredentials = function(email, password) {
  // Outer Promise:
  // - Will eventually resolve with whatever the result it's inner
  //   promise resolves with.
  return user.findOne({ email })
    .then((user) => {
      // Inner Promise:
      // - Will eventually resolve with `user` (which is already
      //   available here), given that the password was correct,
      //   or
      //   reject with the bcrypt.compare `err` if the password was
      //   incorrect.
      return comparePassword(password, user.password)
        .then((result) => {
          // This `then` belongs to the comparePassword Promise.
          // - We use this so we can make sure we return the `user` we picked up
          //   from the previous `user.findOne` Promise.
          // - This ensures that when you chain a `then` to this Promise chain
          //   you always get the `user` and not the result of `comparePassword`
          return user
        })
    })
}


这里的关键是,您在return中的.then()都将作为参数传递给下一个链接的.then()

附加信息:


bcrypt.compare already returns a Promise,因此我们可以避免将其包装到Promise中的整个麻烦。我已将其与回调一起使用,以说明如何处理Promise链中的回调样式代码。

关于javascript - 如何链接Promises和回调样式代码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49163207/

10-14 19:41
查看更多