簡體   English   中英

具有setTimeout的JavaScript串行承諾

[英]JavaScript Serial Promises with setTimeout

我正在使用setTimeouts構建Promise鏈。 所有的Promise都需要串聯而不是並行運行。 我正在使用Bluebird模塊來實現Promise執行的串行流程。

有人可以解釋一下為什么此代碼給我輸出1,2,3,4而不是4,3,2,1嗎?

 var bluebirdPromise = require('bluebird'); function p1(value) { return new Promise(function(resolve, reject) { setTimeout(function(resolve) { console.log(value); resolve; }, value * 1000); }); } var arr = [p1(4), p1(3), p1(2), p1(1)]; bluebirdPromise.reduce(arr, function(item, index, length) { }).then(function (result) { }); 

有幾個問題:

  • 您擁有的console.log並不依賴於先前解決的承諾。 只是超時決定了何時發生輸出。 當您在“相同”時間創建所有四個Promise,因此同時調用了所有四個setTimeout調用時,它們的回調在確定的超時時被調用。 緊隨其后如何鏈接承諾都沒有關系...要解決此問題,您需要將console.log移動到then回調中,因為該回調僅在鏈中的先前承諾已解決時才執行。

  • 您的代碼中未調用resolve函數。 您需要添加括號。

  • setTimeout回調的resolve參數隱藏具有相同名稱的函數:您需要刪除該參數。

這是建議的更正。 對於此代碼段,我已用標准Array#reduce替換了bluebird的reduce ,但它與bluebird的reduce工作原理類似:

 function p1(value) { return new Promise(function(resolve, reject) { setTimeout(function() { // *** resolve(value); // *** }, value * 1000); }); } var arr = [p1(4), p1(3), p1(2), p1(1)]; arr.reduce(function(promise, next) { return promise.then(_ => next).then( value => { console.log(value); // *** return value; }); }, Promise.resolve()); 

如果您有一個Promise-Creator函數p ,並且要以串行方式運行一個Promise 序列 ,則無需加載一個帶有Promise的數組-而是讓它成為一個普通的值數組

注意,我這里也不使用value * 1000 –在您的代碼中,您認為必須使用計算得出的setTimeout延遲人為地編排要按特定順序觸發的承諾。 事實並非如此。 仔細觀察代碼的評價下面來看看我們是如何讓每個承諾之間有1秒鍾的延遲和.then讓事情為了

還要注意,此代碼將在第一個promise解析后立即開始輸出–而不是在輸出所有值之前等待所有promise解析

 const p = x => new Promise(f => setTimeout(f, 1e3, x)) const arr = [4,3,2,1] arr.reduce((acc, x) => acc.then(() => p(x)).then(console.log), Promise.resolve()) 

好的,您可以按順序運行這些承諾,但是為什么呢? 除非以后的步驟某種程度上取決於前面的步驟的結果,否則您沒有理由要放慢它們的速度–即,每個諾言的結果都不依賴於其他諾言,因此,請盡可能快地計算它們。 但是您擔心訂單會丟失,對嗎? 不用擔心,一切都會好起來的-我什至會使用隨機延遲向您顯示,每個承諾的完成時間都無關緊要

 const p = x => new Promise(f => setTimeout(f, 1e3 * Math.random(), x)) const arr = [4,3,2,1] arr.map(p).reduce((acc, x) => acc.then(() => x).then(console.log), Promise.resolve()) 

因此,現在,所有的Promise都可以立即啟動,並且第一個Promise解析后即開始輸出(與Promise.all不同,Promise.all會等待所有Promise完成,然后再提供任何值)。

我只提到這是一種替代方法,因為您提供的示例表明並沒有真正需要按順序執行promise。 您可能天真地簡化了問題的范圍,但只有您知道情況是否如此。

暫無
暫無

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

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