人为的例子
假设我们需要在某些Node应用程序中为Foo
构建Bar
和User
。我们应该实现constructFooForUser
函数,该函数必须使用
callback
函数
Error
Foo
和已创建的Bar
为此,我们必须使用一些数据库函数来获取/创建我们的对象,返回一个Promise。
var constructFooForUser = function(userId, data, callback) {
db.users.find(userId)
.then(function(user) {
if (!user) { return callback(new Error('user not found')); }
db.foos.create(user, data)
.then(function(foo) {
db.bars.create(user, foo, data)
.then(function(bar) {
callback(null, foo, bar);
})
.catch(function(err) {
callback(err);
});
})
.catch(function(err) {
callback(err);
});
})
.catch(function(err) {
callback(err);
});
};
这是构建此类基于承诺的代码的正确方法吗?
我看过Promise代码的示例,看起来像是
doSomething()
.then(doSomethingElse)
.then(doYetAnotherThing)
.then(doLastThing)
.catch(handleError);
但我认为这不适用于这种情况,因为我需要同时使用user,foo和bar,并且链接函数之间不会共享范围。
我问,因为代码看起来很重复,所以我想知道是否有异常。
编辑:忘记在foo
bar
答案 0 :(得分:1)
在我们需要之前,如何将foo
存储在某个变量中?
var constructFooForUser = function(userId, data, callback) {
var gFoo;
db.users.find(userId)
.then(function(user) {
if (!user) { return callback(new Error('user not found')); }
return db.foos.create(user, data)
})
.then(function(foo) {
gFoo = foo;
return db.bars.create(user, data)
})
.then(function(bar) {
callback(null, gFoo, bar);
})
.catch(function(err) {
callback(err);
});
};
答案 1 :(得分:1)
我通常(并且我认为这是一个hacky解决方法)在我去的时候将结果累积在一个数组中。
firstThing()
.then(first => Promise.all([first, secondThing]))
.then(([first, second]) => Promise.all([first, second, thirdThing()]))
.catch(e => handleErr(e));
这种积累模式有效,而且对于ES 2015解构,其太笨重。
答案 2 :(得分:0)
var constructFooForUser = function(userId, data, callback) {
db.users.find(userId).then(function(user) {
//because rejecting a promise means nothing else than throwing an Error
if(!user) throw new Error('user not found');
//resolves as soon as both requests have been resolved.
//rejects if _any_ of the requests is rejecting
return Promise.all([
db.foos.create(user, data),
db.foos.create(user, data)
]);
}).then(
([foo, bar]) => callback(null, foo, bar), //utilizing array destructuring
(err) => callback(err)
);
}
我正在使用.then(a, b)
而不是.then(a).catch(b)
,因为后者还会捕获回调函数中抛出的错误(我们不希望这样);你有责任处理它们。它会隐藏代码中的错误,错误消息根本不会显示在控制台中。
即使您对嵌套承诺的尝试也可以通过返回承诺并连接至少错误部分来简化
var constructFooForUser = function(userId, data, callback) {
db.users.find(userId)
.then(function(user) {
if (!user) throw new Error('user not found');
return db.foos.create(user, data)
.then( foo => db.bars.create(user, data).then( bar => callback(null, foo, bar) ) );
})
.catch(function(err) {
callback(err);
});
};