簡體   English   中英

如何正確處理父異步調用中的一系列異步調用

[英]How to correctly handle a series of async calls inside a parent async call

我有一個用例,我想進行異步調用(認為它類似於 ajax),然后在該調用的成功塊中,我想使用父調用生成的 id 在循環中進行一系列異步調用。 我的要求是:

  1. 我把顯示成功吐司的代碼放在哪里? 目前我把它放在成功塊內的 for 循環之后,但它有一個問題,它會在子異步調用完成之前被執行,因為 for 循環不會等待調用並且會立即執行並且代碼會運行以示成功干杯。
  2. 如果任何一個子調用失敗,則不應發生進一步的調用(這更多是從效率的角度來看),而且在這種情況下,我應該能夠刪除創建的父記錄,因此如何處理還有嗎? 提前致謝!

示例代碼片段:

asyncCallA(inputId)
    .then(output => {
        // inputIdsForChildCalls is the list of inputIds for child async 
        // calls
        inputIdsForChildCalls = [do something with output]
        for (let i = 0; i < inputIdsForChildCalls.length; i++) {
            asyncCallB(inputIdsForChildCalls[i])
                .then(output => {
                    // do something
                })
                .catch(error => {
                    // do something with error
                });
        }
        showSuccessToast("Records created successfully!");
    })
    .catch(error => {
        // do something with error
    });

由於聽起來您想連續運行asyncCallB()以便您可以在其中一個失敗時避免任何額外的調用,那么這將是使用async/await最容易實現的。

為此,您必須將包含函數標記為async以便您可以使用await 然后,您可以使用await對異步操作進行排序:

async function someFunc(inputId) {
    try {
        let output = await asyncCallA(inputId);
        // inputIdsForChildCalls is the list of inputIds for child async 
        // calls
        let inputIdsForChildCalls = [do something with output]
        for (let childId of inputIdsForChildCalls) {
            let childResult = await asyncCallB(inputIdsForChildCalls[childId]);
            // process child result here
            // errors in asyncAllB() will have gone to the catch(e) statement below
        }
        showSuccessToast("Records created successfully!");
    } catch(e) {
        // handle error here
        // throw an error here if you want the caller to be able to see the error
    }
}

為了獲得更快的性能,您可以並行運行asyncCallB()操作,如下所示,但所有asyncCallB()調用都將運行,即使第一個調用有錯誤(因為它們都是並行啟動的):

async function someFunc() {
    try {
        let output = await asyncCallA(inputId);
        // inputIdsForChildCalls is the list of inputIds for child async 
        // calls
        let inputIdsForChildCalls = [do something with output]
        let allResults = await Promise.all(inputIdsForChildCalls.map(childId => {
            return asyncCallB(childId);
        }));
        // process allResults array here
        // errors will have gone to the catch(e) statement below
        showSuccessToast("Records created successfully!");
    } catch(e) {
        // handle error here
    }
}
asyncCallA(inputId)
.then(output => {
    inputIdsForChildCalls = [do something with output]
    Promise.all(inputIdsForChildCalls)
        .then(outputs => {
            // do something
            showSuccessToast("Records created successfully!");
        })
        .catch(error => {
            // do something with error
        });
    }
})
.catch(error => {
    // do something with error
});
asyncCallA(inputId)
    .then(output => {
        inputIdsForChildCalls = [do something with output]
        let syncCalls = [];
        for (let i = 0; i < inputIdsForChildCalls.length; i++) {
            syncCalls.push(asyncCallB(inputIdsForChildCalls[i]));
        }
        Promise.all(inputIdsForChildCalls)
           .then(outputs => {
            // do something
            showSuccessToast("Records created successfully!");
           })
        .catch(error => {
            // do something with error
        });
    })
    .catch(error => {
        // do something with error
    });

確保異步鏈接發生的最佳選擇是使用 array.reduce 函數,下面是相同的示例代碼。

如果您不清楚 array.reduce 和 promise 是如何工作的。 我建議你參考這篇文章。

https://developers.google.com/web/fundamentals/primers/promises

下面是示例代碼,您可以使用它。

asyncCallA(inputId)
    .then(output => {
        // inputIdsForChildCalls is the list of inputIds for child async 
        // calls
        inputIdsForChildCalls = [];

        inputIdsForChildCalls.reduce(function(sequence, Id)
        {
            return sequence.then(function()
          {
             return asyncCallB(Id);
          }).then(function(asyncCallResult)
                {
              //do something
        });
        }, Promise.resolve())

    })
    .then(function()
    {
        showSuccessToast("Records created successfully!");
    })
    .catch(error => {
        // do something with error
    });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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