您是否可以避免与Promises一起嵌套? [英] Can you avoid nesting altogether with Promises?
问题描述
据我了解,Promises的主要卖点之一是能够编写平面代码(或者比回调地狱更扁平).
From what I understand one of the main selling points for Promises is the ability to write flat code (or, flatter than callback hell).
尽管在很多情况下,为了使用闭包,我们需要嵌套promise.例如(来自 q 的文档,尽管我使用的是Bluebird):
Though it seems that in many cases we need to nest promises, in order to use closure. For example (from q's docs, though I use Bluebird):
function authenticate() {
return getUsername()
.then(function (username) {
return getUser(username);
})
// chained because we will not need the user name in the next event
.then(function (user) {
return getPassword()
// nested because we need both user and password next
.then(function (password) {
if (user.passwordHash !== hash(password)) {
throw new Error("Can't authenticate");
}
});
});
}
是否有一种更干净的方法而不嵌套?
Is there a cleaner way to do this, without nesting?
我已经设法使用.all
清理了这个特定的示例,但是在更复杂的情况下,我认为无法做到这一点:
I've managed to clean up this specific example using .all
, but there are more complex cases where I don't think it can be done:
function authenticate() {
return Promise.all([
getUsername().then(getUser),
getPassword()
]).spread(function (user, password) {
if (user.passwordHash !== hash(password)) {
throw new Error('Can\'t authenticate');
}
});
}
推荐答案
是的,您始终可以使用Promise作为代理,使用Promise.all
(Bluebird中的Promise.join
的简写形式)来平整Promise链.毕竟-Promise抽象值,您总是可以在需要时解开Promise,并使其他变量依赖于此.
Yes, you can always flatten a promise chain with Promise.all
(shorthand through Promise.join
in Bluebird) by using promises for the proxies they are. After all - promises abstract values, you can always unwrap a promise as late as you want and have other variables depend on it.
是否更具可读性是另一个争论:
Whether or not it's more readable is another debate:
foo().then(function(a){
return bar(a).then(function(b){
return g(a,b); // "needed" to nest because I wanted `a`
});
});
可以写为:
var a = foo();
var b = a.then(bar);
Promise.join(a, b, function(a,b){
return g(a, b); // alternatively, res could have been `Promise.join(a,b, g)`
});
所以通常-您可以总是避免嵌套,但是很多时候您可能不想这么做.
So generally - you can always avoid nesting but a lot of time you might not want to.
就您而言,甚至可以是:
In your case, this can even be:
function authenticate() {
var userPass = Promise.all([ getUsername().then(getUser), getPassword()]);
var passHash = userPass.get(0).get("passwordHash");
var newHash = userPass.get(1).then(hash);
var equal = Promise.join(userHash, newHash, function(a, b){ return a !==b });
return equal.then(function(val){ if(!val) throw new Error("..."); });
}
扑吗?当然.更好的?这是另一个问题.如果您有嵌套的for
循环,则可能希望将其保留为嵌套的for
循环并嵌套,而不是乱砍该选项并使用单个循环.
Flatter? Sure. Better? That's a whole other question. If you have a nested for
loop, you might want to keep it a nested for
loop and nest rather than hack around that option and use a single loop.
这篇关于您是否可以避免与Promises一起嵌套?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!