使用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();
}
};