通过这个简单的例子理解承诺链

时间:2018-05-07 18:07:17

标签: javascript typescript promise

我需要以下逻辑,但我无法得到它。当找到用户(不是undefined)时,我需要比较返回boolean的密码(另一个承诺)。需要:

  • 当用户不存在时返回undefined(HTTP 404)
  • 密码错误时
  • 抛出ForbiddenError(HTTP 403)
  • 当用户存在且密码匹配时,
  • 返回user(HTTP 200)

第一次尝试(丑陋,不可读):

  @Post()
  login(
    @BodyParam('username', { required: true }) username: string,
    @BodyParam('password', { required: true }) plainPassword: string,
  ) {

    return this.userRepository.findOne({ username: username, enable: true })
      .then ((user: User | undefined) => {
        if (!user) {
          return undefined; // 404
        }

        return bcrypt.compare(plainPassword, user.password)
          .then(passwordMatch => {
            if (!passwordMatch) {
              throw new ForbiddenError('Authentication failed.'); // 403
            }

            return user; // 200
          });
      });
  }

第二次尝试不起作用,总是返回'ok'

return this.userRepository.findOne({ username: username, enable: true })
  .then((user: User | undefined) => {
    if (!user) {
      return undefined; // 404
    }

    return bcrypt.compare(password, user.password);
  })
  .then(passwordMatch => {
    // Doesn't work: this is executed every time (even if user is undefined).

    return 'ok';
  });

2 个答案:

答案 0 :(得分:3)

最后你的then处理程序总是运行(如果promises不拒绝),因为如果用户不存在,或者使用布尔值,第一个promise将以undefined解析如果用户确实存在。

您的嵌套版本没问题。如果你需要在成功案例中返回user,那么可能就是这样。

但是,如果您只需要在成功案例中的第二个代码示例中返回'ok',那么可以展平事物,您只需处理undefined您如果没有用户,我会得到的。如果找不到用户,我们也可以利用您知道user将具有值undefined的事实:

return this.userRepository.findOne({ username: username, enable: true })
  // The `then` below returns `undefined` if `user` is `undefined`, the promise from `compare` otherwise
  .then((user: User | undefined) => user && bcrypt.compare(password, user.password))
  .then(passwordMatch => {
    if (passwordMatch === undefined) {
      // No user
      return undefined;
    } else if (!passwordMatch) {
      // Bad password
      throw new ForbiddenError('Authentication failed.'); // 403
    } else {
      // All good
      return 'ok';
    }
  });

如果要展平返回user,则需要将user传播到下一个处理程序:

return this.userRepository.findOne({ username: username, enable: true })
  .then((user: User | undefined) => {
    return !user
        ? {user} // will be {undefined}
        : bcrypt.compare(password, user.password)
            .then(passwordMatch => ({user, passwordMatch})); // *** Note making an object
  })
  .then(({user, passwordMatch}) => { // *** Note destructuring
    if (user === undefined) {
      // No user
      return undefined;
    } else if (!passwordMatch) {
      // Bad password
      throw new ForbiddenError('Authentication failed.'); // 403
    } else {
      // All good
      return user; // 200
    }
  });

(第一个then处理程序可能是上面第一个代码块中的简明箭头,但它开始变得难看。)

答案 1 :(得分:0)

当您return undefined时,这会使第一个then()回调的承诺解析为undefined

然后执行第二个then()回调,接收undefined作为参数。

您应该更改第二个回调以检查它。