[英]How to use Promise and setTimeout within a generator function in order to create an async generator?
我正在嘗試編寫一個生成器 function 來創建一個異步生成器。 生成器應該在某個時間產生一個延遲值,每個延遲值都通過 promise。該值和相關延遲(以毫秒為單位)來自兩個不同的 arrays。
至於提供的示例代碼,預期的行為是一個記錄序列,其中一個接一個地等待另一個, target
數組中的每個value
都被記錄下來,並記錄了從timeArray
到target
結束的相關(相同索引) 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.