簡體   English   中英

Node.js:具有分支的串行操作

[英]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.forEachOfSeriesasync.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可以減輕痛苦,並且可以大大簡化健壯的錯誤處理工作並將其與其他異步操作接口。

這里使用的諾言的主要關鍵是:

  1. 使所有異步操作返回以值解析的promise或以失敗為原因的拒絕。
  2. 然后,您可以將.then()處理程序附加到任何promise上,以查看異步操作成功完成或出現錯誤的時間。
  3. .then()的第一個回調是成功處理程序,第二個回調是錯誤處理程序。
  4. 如果從.then()處理程序中返回承諾,則該承諾將“鏈接”到前一個承諾,因此所有成功和錯誤狀態都將鏈接起來,並返回到原始的承諾狀態。 這就是為什么您看到上面的代碼總是返回嵌套的Promise的原因。 這樣可以自動將錯誤返回到調用方,並允許您將值一直返回到調用方,即使深度嵌套的Promise也是如此。
  5. 如果以上代碼中的任何承諾被拒絕,那么它將停止該承諾鏈,直到找到實際的拒絕處理程序並將該錯誤傳播回該拒絕處理程序。 由於上述代碼中唯一的拒絕處理程序處於to級別,因此所有錯誤都可以在那里捕獲並看到,無論它發生在嵌套的異步混亂中有多深(嘗試使用簡單的回調可靠地進行操作-這非常困難)。

原生承諾

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM