我是node.js的新手,并将其用于从syslog消息中获取数据并将其存储到数据库的后端。
我遇到了以下类型的串行操作:
1. Query the database
2. If the query value is X do A. otherwise do B.
A. 1. Store "this" in DB
2. Query the database again
3. If the query value is Y do P. otherwise do Q.
P. Store "something"
Q. Store "something else"
B. 1. Store "that" in the DB
2. Store "the other thing" in the DB
这里的要点是我有一些操作需要按顺序进行,但顺序中有分支逻辑。
我最终陷入了回调地狱(当我来到Node时,我不知道那是什么......我现在这样做)。
我已将async
库用于更直接的事情 - 例如按async.forEachOfSeries
或async.queue
执行操作。但我不认为如果事情必须按顺序发生但有分支就有办法使用它。
有没有办法处理这个不会导致回调的地狱?
答案 0 :(得分:3)
这样的任何类型的复杂逻辑实际上都会从每个异步操作使用promise中受益,特别是当你处理错误时,也只是为了构造逻辑流程。
由于您还没有提供任何实际代码,我将举一个例子。假设您有两个核心异步操作,它们都返回一个承诺:query(...)
和store(...)
。
然后,您可以像这样实现上述逻辑:
query(...).then(function(value) {
if (value === X) {
return store(value).then(function() {
return query(...).then(function(newValue) {
if (newValue === Y) {
return store("something");
} else {
return store("something else");
}
})
});
} else {
return store("that").then(function() {
return store("the other thing");
});
}
}).then(function() {
// everything succeeded here
}, function(err) {
// error occurred in anyone of the async operations
});
我不会假装这很简单。无论你如何操作,在七种不同的异步操作中实现逻辑流程只是一些代码。但是,承诺可以减少其他方面的痛苦,并且更容易进行强大的错误处理工作,并将其与其他异步操作联系起来。
这里使用的承诺的主要关键是:
.then()
处理程序附加到任何承诺,以查看异步操作何时成功完成或出错。.then()
的第一个回调是成功处理程序,第二个回调是错误处理程序。.then()
处理程序中返回一个承诺,那么该承诺将被链接到#34;到前一个,所以所有成功和错误状态都被链接并返回到原始的promise状态。这就是为什么你看到上面的代码总是返回嵌套的promises。这样可以自动将错误返回给调用者,并允许您将值一直返回给调用者,即使是深层嵌套的promise也是如此。Node.js已经内置了承诺,因此您可以使用本机承诺。但是,node.js实现的promise规范并不是特别丰富,因此很多人使用promise库(我使用Bluebird进行所有node.js开发)来获得其他功能。其中一个更突出的特点是能够实现" promisify"现有的非承诺API。这允许您获取仅适用于回调的函数,并创建一个通过promise工作的新函数。我发现这特别有用,因为许多已经存在一段时间的API本身并不会返回承诺。
假设您有一个使用传统回调的异步操作,并且您希望"宣传它"。以下是您可以手动执行此操作的示例。假设你有db.query(whatToSearchFor, callback)
。您可以像这样手动宣传:
function queryAsync(whatToSearchFor) {
return new Promise(function(resolve, reject) {
db.query(whatToSearchFor, function(err, data) {
if (!err) {
reject(err);
} else {
resolve(data);
}
});
});
}
然后,您只需致电queryAsync(whatToSearchFor)
并使用返回的承诺。
queryAsync("foo").then(function(data) {
// data here
}, function(err) {
// error here
});
或者,如果你使用类似Bluebird promise library的东西,它有一个函数用于宣传任何异步函数,它通过作为最后一个参数传递的node.js样式回调来传递其结果:
var queryAsync = Promise.promisify(db.query, db);