[英]Node.js: serial operations with branching
我是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
。 但是,我認為如果事情必須按順序進行但有分支,就沒有辦法使用它。
有沒有辦法處理不會導致回調地獄的情況?
像這樣的任何復雜邏輯都將真正受益於對每個異步操作使用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
});
我不會假裝這很簡單。 無論如何執行,在七個不同的異步操作之間實現的邏輯流程將只是一些代碼。 但是,promise可以減輕痛苦,並且可以大大簡化健壯的錯誤處理工作並將其與其他異步操作接口。
這里使用的諾言的主要關鍵是:
.then()
處理程序附加到任何promise上,以查看異步操作成功完成或出現錯誤的時間。 .then()
的第一個回調是成功處理程序,第二個回調是錯誤處理程序。 .then()
處理程序中返回承諾,則該承諾將“鏈接”到前一個承諾,因此所有成功和錯誤狀態都將鏈接起來,並返回到原始的承諾狀態。 這就是為什么您看到上面的代碼總是返回嵌套的Promise的原因。 這樣可以自動將錯誤返回到調用方,並允許您將值一直返回到調用方,即使深度嵌套的Promise也是如此。 Node.js現在內置了promise,因此您可以使用本機promise。 但是,node.js實現的promise規范並不具有特別豐富的功能,因此許多人都使用promise庫(我在所有node.js開發中都使用了Bluebird)來獲取其他功能。 更為突出的功能之一是能夠“承諾”現有的非承諾API。 這使您可以采用僅適用於回調的函數,並創建通過諾言起作用的新函數。 我發現這特別有用,因為已經存在了一段時間的許多API本身都不返回promise。
假設您有一個使用傳統回調的異步操作,並且您想“實現”。 這是如何手動執行此操作的示例。 假設您有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(whatToSearchFor)
。
queryAsync("foo").then(function(data) {
// data here
}, function(err) {
// error here
});
或者,如果您使用類似Bluebird Promise 庫之類的東西,則它具有一個函數,用於使任何異步函數(通過最后一個參數傳遞的node.js樣式回調傳遞其結果):
var queryAsync = Promise.promisify(db.query, db);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.