簡體   English   中英

將無限for循環中的await轉換為raw promise.then

[英]Converting await in infinite for loop into raw promise.then

據我所知, async/await只是對promise.then語法糖。 請考慮以下代碼段:

function sleep(n){
    return new Promise(res => setTimeout(res, n));
}

function* range(n){
    var i = 0;
    while(i < n)    yield i++;
}
async function doStuff(){
    for(let n of range(10)){
        console.log(n);          // print the number
        await sleep(1000);       // wait for 1 second
    }
}

async/await使代碼非常線性,高效且易於理解。 要記住的一件事是, range不必具有實際結束。

現在的問題是如何使用pre-ES7時代的promise.then來重寫它promise.then 這是同一循環的可能實現:

function doStuff(){
    return Array.from(range(10)).reduce((acc, ele) => {
        return acc
            .then(() => console.log(ele))
            .then(() => sleep(1000))
    }, Promise.resolve());
}

忽略代碼不太優雅的事實,使用Array.from(range(10))

  1. 創建一個不需要的額外數組,並且
  2. 假設range(10)將在未來結束某一點。

看起來不是很好的轉換。

我們也可以通過使用yield作為await來完全重新發明輪子,但這會使語法不符合ES5。 這里的目標是:

  1. 使用符合ES5的語法重寫
  2. 使用promise-returning sleep功能
  3. 動態鏈接sleep承諾,同時允許迭代器沒有結束
  4. doStuff可以鏈接:

     doStuff().finally(cleanUp); // clean up if something failed 
  5. (可選)代碼不應過於復雜

任何的想法?

我認為以下可能會有這個技巧,你的例子沒有說明如何處理解析值以及它與迭代器值的關系,所以我改變了如何調用sleep。

一些承諾polyfils可能會耗盡具有高promise鏈的堆棧空間,所以你應該檢查你的polyfil(如果它的實現返回並繼續使用setTimeout,堆棧應該清除,但是一些polyfils可能不會以這種方式實現它)。

  function sleep(n){ return new Promise(res => setTimeout(_=>res(n/100), n)); } function* range(n){ var i = 0; while(i < n) yield i++; } function doStuff(){ const processValue = resolve => { console.log("resolved with:",resolve); // if(resolve===3){throw "nope";} return sleep(resolve*100); }, rec = (p,iter) => { const result = iter.next(); if (result.done){ return p; } p = p.then(_=>processValue(result.value)) return p.then( resolve=>{ return rec(p,iter) } ); }, iter = range(10), firstResult = iter.next(); if(firstResult.done){ return processValue(firstResult.value); } return rec(processValue(firstResult.value),iter); } doStuff() .then( x=>console.log("done:",x) ,reject=>console.warn("fail:",reject) ); 

我總是說如果你需要一個異步設計模式,首先要看一下異步庫。 在這種情況下,由於您正在使用promises,請查看promisified async-q庫。 翻譯很簡單:

var n = 0;
async.whilst(() => n < 10, () => {
    n++;
    console.log(n);
    return sleep(1000);
})

暫無
暫無

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

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