[英]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.