异步功能使Node.js非常强大和快速。但是,我们假设您正在制作一个类似Express的Web应用程序,并且您有一个表单供访问者填写。提交表单时,它会将数据通过电子邮件发送给某人,并将数据保存到数据库中。
现在使用Node,我的第一直觉就是做这样的事情(伪代码):
sendEmailToSomeone(data, function(err, success){
if (err) { ... }
// email sent successfully
});
insertIntoDatabase(data, function(err, success){
if (err) { ... }
// successful database insertion
});
res.redirect('/thank-you'); // Redirect user to "Thank you" page
因此,您有两个同时发生的异步功能,将发送电子邮件并将数据放入数据库。并且访问者被重定向到某种类型的"感谢您提交表单"页面,而这些事情发生在服务器上。这利用了Node.js异步功能。
但如果这两个异步函数中的一个出错,你会怎么做?也许电子邮件发送失败或数据库服务器脱机?如何向访问者提供错误反馈,因为他们已被重定向?
你是否使用Promises或其他东西并迫使访问者等待两个异步函数完成之后再给他们"谢谢你"消息或"提交表单时出错#34;信息?如果你采用这种方法,那么你首先会失去使用Node.js的异步优势,而你实际上是在仿效PHP类型的响应。
最好的方法是什么?
答案 0 :(得分:0)
所有可能的答案都会以某种方式产生偏差,所以我向我解释一下。到目前为止,我已经看到,主要是用适当的库控制异步代码执行,例如Async或Q。特别是Async.seq可以优雅地帮助您。库中的示例:
// Requires lodash (or underscore), express3 and dresende's orm2.
// Part of an app, that fetches cats of the logged user.
// This example uses `seq` function to avoid overnesting and error
// handling clutter.
app.get('/cats', function(request, response) {
var User = request.models.User;
async.seq(
_.bind(User.get, User), // 'User.get' has signature (id, callback(err, data))
function(user, fn) {
user.getCats(fn); // 'getCats' has signature (callback(err, data))
}
)(req.session.user_id, function (err, cats) {
if (err) {
console.error(err);
response.json({ status: 'error', message: err.message });
} else {
response.json({ status: 'ok', message: 'Cats found', data: cats });
}
});
});
但你可能会发现这个简单的&没有光泽或不适当。然后你可以使用Promises。在你的场景中Promise.All会很好。库中的示例:
Promise.all([Promise.resolve('a'), 'b', Promise.resolve('c')])
.then(function (res) {
assert(res[0] === 'a')
assert(res[1] === 'b')
assert(res[2] === 'c')
})