如何简化深层嵌套的承诺
How to simplify deep nested promises
我遇到过这样一种情况,我需要在 then()
中的每个 "else" 子句处中断,这看起来并不比嵌套回调好多少,这是一个登录过程:
User.findOne({
username: username
}).exec()
.then(user => {
if (user) {
return user.verifyPassAsync()
.then(matched => {
if (matched) {
return User.getBriefProfile(username))
.then(emp => {
if (emp) {
return saveToSession(emp);
} else {
//return
}})
} else {
//return ...
}})
} else {
// return false
}
})
有什么办法可以简化这个吗?
不是真的,因为您不是(仅)在此处嵌套承诺而是条件语句。如果用 async/await (ES7) 编写,你的函数看起来像
var user = await User.findOne({username}).exec();
if (user) {
var matched = await user.verifyPassAsync();
if (matched) {
var emp = await User.getBriefProfile(username);
if (emp) {
return saveToSession(emp);
} else {
// return …;
}
} else {
// return …;
}
} else {
// return …;
}
如您所见,嵌套是程序固有的。虽然它已经有点简化了(没有嵌套 then
调用),你现在可以使用 Promise.coroutine
和 ES6 生成器来做到这一点。
你最好的选择可能是 throw
每个 else
中的一个错误,然后用它线性化链,最后 .catch
对它进行处理。当然,如果你在每个 else
块中做同样的事情,那么你也可以写
var user = await User.findOne({username}).exec();
if (user)
var matched = await user.verifyPassAsync();
if (matched)
var emp = await User.getBriefProfile(username);
if (emp) {
return saveToSession(emp);
else
// return …;
这很容易转换回 then
回调:
User.findOne({username: username}).exec()
.then(user =>
user && user.verifyPassAsync()
).then(matched =>
matched && User.getBriefProfile(username);
).then(emp =>
emp ? saveToSession(emp) : …;
);
我遇到过这样一种情况,我需要在 then()
中的每个 "else" 子句处中断,这看起来并不比嵌套回调好多少,这是一个登录过程:
User.findOne({
username: username
}).exec()
.then(user => {
if (user) {
return user.verifyPassAsync()
.then(matched => {
if (matched) {
return User.getBriefProfile(username))
.then(emp => {
if (emp) {
return saveToSession(emp);
} else {
//return
}})
} else {
//return ...
}})
} else {
// return false
}
})
有什么办法可以简化这个吗?
不是真的,因为您不是(仅)在此处嵌套承诺而是条件语句。如果用 async/await (ES7) 编写,你的函数看起来像
var user = await User.findOne({username}).exec();
if (user) {
var matched = await user.verifyPassAsync();
if (matched) {
var emp = await User.getBriefProfile(username);
if (emp) {
return saveToSession(emp);
} else {
// return …;
}
} else {
// return …;
}
} else {
// return …;
}
如您所见,嵌套是程序固有的。虽然它已经有点简化了(没有嵌套 then
调用),你现在可以使用 Promise.coroutine
和 ES6 生成器来做到这一点。
你最好的选择可能是 throw
每个 else
中的一个错误,然后用它线性化链,最后 .catch
对它进行处理。当然,如果你在每个 else
块中做同样的事情,那么你也可以写
var user = await User.findOne({username}).exec();
if (user)
var matched = await user.verifyPassAsync();
if (matched)
var emp = await User.getBriefProfile(username);
if (emp) {
return saveToSession(emp);
else
// return …;
这很容易转换回 then
回调:
User.findOne({username: username}).exec()
.then(user =>
user && user.verifyPassAsync()
).then(matched =>
matched && User.getBriefProfile(username);
).then(emp =>
emp ? saveToSession(emp) : …;
);