簡體   English   中英

如何在生成器 function 中使用 Promise 和 setTimeout 來創建異步生成器?

[英]How to use Promise and setTimeout within a generator function in order to create an async generator?

我正在嘗試編寫一個生成器 function 來創建一個異步生成器。 生成器應該在某個時間產生一個延遲值,每個延遲值都通過 promise。該值和相關延遲(以毫秒為單位)來自兩個不同的 arrays。

至於提供的示例代碼,預期的行為是一個記錄序列,其中一個接一個地等待另一個, target數組中的每個value都被記錄下來,並記錄了從timeArraytarget結束的相關(相同索引) delay數組的迭代。

我嘗試使用下面顯示的代碼,但它只打印出timeArray中的前 2 個元素,但它不打印所有其他元素,我不確定它是否在timeArray的前兩個時間間隔后打印它們

let j = 0;

// Array that shows how long after each number printed
// to the console the next value should be printed.
var timeArray = [6, 68, 51, 41, 94, 65, 47, 85, 76, 136];

// Array of numbers that should be printed.
var targets = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7];

let generator = generateSequence();

async function* generateSequence(casiInfluence) {
  yield new Promise((resolve, reject) => {
    setTimeout(() => resolve(console.log(targetArray[j]), timeArray[j]); console.log(timeArray[j]);
  });
}
(async function main() {
  for await (var result of generateSequence()) {
    console.log(result);
    j++;
    result = generator.next();
  }
}());

對於延遲值生成器的每一步,OP 都可以實現自己的任務……比如……

  • 將兩個 OP 的 arrays 映射到一個更好的可處理數據結構中......這里是一個元組數組,其中每個元組由...... [<value>, <delay>]組成。

  • 將每個值延遲元組映射到延遲值操作,這是一個異步 function,它創建並返回一個 promise,它將在毫秒delay后解析value ,其中創建異步 function 的映射 function 稱為createDeferredValue

  • 從異步函數數組創建異步生成器,其中生成器 function 稱為createPoolOfDeferredValues

 // - a specific helper which creates an async function // (encapsulating a promise) for each to be deferred value. function createDeferredValue(value, delay) { return async function () { return await ( new Promise(resolve => setTimeout(resolve, delay, value)) ); }; } // - another helper which creates an async generator // from an array of async functions. async function* createPoolOfDeferredValues(deferredValueList) { const asyncFunctions = [...deferredValueList]; let asyncFct; while (asyncFct = asyncFunctions.shift()) { yield (await asyncFct()); } } // - array that defines how long after each to be // processed value the next value will be processed. const valueDelays = [600, 680, 510, 410, 940, 650, 470, 850, 760, 1360]; // - array of to be processed target values. const targetValues = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7] // - maps both above OP's arrays into a // better processable data-structure. const targetEntries = targetValues.map((value, idx) => [value, valueDelays[idx]]); console.log({ targetEntries }); // - helper task which creates a list of async functions. const deferredValueList = targetEntries.map(([value, delay]) => createDeferredValue(value, delay) ); // create an async generator... const poolOfDeferredValues = createPoolOfDeferredValues(deferredValueList); (async () => { //... and iterate over it. for await (const value of poolOfDeferredValues) { console.log({ value }); } })(); console.log('... running...');
 .as-console-wrapper { min-height: 100%;important: top; 0; }

但是當然,一旦創建了異步函數的列表/數組,就可以直接使用for...await對其進行迭代,而無需繞過異步生成器。 因此,上面提供的代碼簡化為......

 // - a specific helper which creates an async function // (encapsulating a promise) for each to be deferred value. function createDeferredValue(value, delay) { return async function () { return await ( new Promise(resolve => setTimeout(resolve, delay, value)) ); }; } // - array that defines how long after each to be // processed value the next value will be processed. const valueDelays = [600, 680, 510, 410, 940, 650, 470, 850, 760, 1360]; // - array of to be processed target values. const targetValues = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7] // - maps both above OP's arrays into a // better processable data-structure. const targetEntries = targetValues.map((value, idx) => [value, valueDelays[idx]]); console.log({ targetEntries }); // - helper task which creates a list of async functions. const deferredValueList = targetEntries.map(([value, delay]) => createDeferredValue(value, delay) ); (async () => { // - iterate the list of async functions by `for...await`. for await (const deferredValue of deferredValueList) { const value = await deferredValue(); console.log({ value }); } })(); console.log('... running...');
 .as-console-wrapper { min-height: 100%;important: top; 0; }

您使用let generator = generateSequence()創建了生成器,但您從未對其進行迭代。

(這是分散的,使用了更多的變量名,所以更容易閱讀):

var timeArray = [6, 68, 51, 41, 94, 65, 47, 85, 76, 136];//Array that shows how long after each number printed to the console the next value should be printed
var targets = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7];//Array of numbers that should be printed

var generator = generateSequence();

( async () => {

    for await ( const printNumber of generator ) {
        /* Accessing the generator's properties logs to the console, so... 
           Nothing to do in this for{} loop. */
    }

} )()

async function* generateSequence() {
    for ( const i in timeArray ) {
        const delay = timeArray[ i ];
        const numberToPrint = targets[ i ];
        await waitForPrint( numberToPrint, delay );
        yield;
    }
}

function waitForPrint( text, delay ) {
    return new Promise( (resolve,reject) => {
        setTimeout(
            () => {
                console.log( text );
                resolve();
            },
            delay
        )
    })
}

如果沒有生成器,這會更容易:


var timeArray = [6, 68, 51, 41, 94, 65, 47, 85, 76, 136];//Array that shows how long after each number printed to the console the next value should be printed
var targets = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7];//Array of numbers that should be printed


for( let scheduledTimeMS=0, i=0; i<timeArray.length; i++ ) {

    const numberToPrint = targets[ i ];
    const delay = timeArray[ i ];

    scheduledTimeMS += delay;

    setTimeout( () => console.log( numberToPrint ), scheduledTimeMS );

}

暫無
暫無

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

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