Javascript "Run To Completion"

使用Javascript也有几个月的时间了,今天发现了这个一个让我诧异事情:

Promise 的resolve和reject方法

我需要在使用Node写一个在数据库中插入用户的函数,代码如下:

const add = (email, password, repassword) => {
  return new Promise((resolve, reject) => {
    if (!password) {
      reject(new Error("password can't be empty"));
    }

    if (password !== repassword) {
      reject(new Error("password is not equals to repeat password"));
    }

    if (!validatePassword(password)) {
      reject(new Error('Password must contains at least: 2 lower case letters, 2 upper case letters  and 2 digits'));
    }

    const {salts} = security;
    pwd.hash(password, salts, (error, hash) => {
      if (error) reject(error);

      getUserByEmail(email)
        .then(user => {
          if (user) {
            reject(new Error('email already exist'));
          }

          insertAdminUser(email, hash)
            .then(result => resolve(result))
            .catch(error => reject(error));
        });
    });

  });
};

验证不成功调用reject,最后添加用户成功调用resolve,看起一切都很好。但是当我添加一个不符合验证要求的password,如:

add("ishuiyutian@gmail.com", "123456", "123456")
  .then(result => {})
  .catch(error => {
    console.log(`add user failed, error: ${error}`);
  });

如我所期望的那样,程序逻辑进入了catch中,打印出了:
add user failed, error:'Password must contains at least: 2 lower case letters, 2 upper case letters and 2 digits

但是出乎意料的是,数据库中同时生成了一条username: ishuiyutian@gmail.com, password: 123456记录,这说明程序逻辑走到了insertAdminUser,调用insertAdminUser生成了那条记录。

也就是说,当调用reject后,Promise并没有停下来,而是继续执行了下去。

在网上查了查,得到了这个的结论:

Javascript 有一个 “Run To Completion”的概念,这个概念是这样子的:

Unless an error is thrown, a function is executed until a return
statement or its end is reached. Other code outside of the function can’t interfere with that (unless, again, an error is thrown).

也就是说,除非程序抛出了一个异常,否则这个function将会继续执行,直到遇到return这个statement或者这个程序已经运行到了结尾。在这个function外部的其它代码不能干扰它的执行。

所以,如果我们想使用reject()后并返回,我们需要在它前面加上return,如:

if (!password) {
   return reject(new Error("password can't be empty"));
}

Express 的next方法

对于express 的next方法也是同样的情况,如下代码:

export const checkUserDeletePermission = ({userId}, res, next) => {
  if (!doesUserHaveDeleteFunctionPermission(userId)) {
    next(new UnauthorizedException('You are not permitted to delete'));
  } 
  next();
};

如果代码逻辑进入到了if代码块中,执行了next(new UnauthorizedException('You are not permitted to delete listing'))方法,但是后程序并没结束,它依然会执行后面的next()方法,直到这个函数执行完成。

所以,最好是将后面的next()放在else块中,如:

export const checkUserDeletePermission = ({userId}, res, next) => {
  if (!doesUserHaveDeleteFunctionPermission(userId)) {
    next(new UnauthorizedException('You are not permitted to delete'));
  } else {
    next();
  }
};
    原文作者:水雨田
    原文地址: https://www.jianshu.com/p/d256a0c4ffd3
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞