简体   繁体   English

如何在生成器 function 中使用 Promise 和 setTimeout 来创建异步生成器?

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

I'm trying to write a generator function which creates an async generator.我正在尝试编写一个生成器 function 来创建一个异步生成器。 The Generator should yield a deferred value at time, each via a promise. The value and the related delay (in milliseconds) come from two different arrays.生成器应该在某个时间产生一个延迟值,每个延迟值都通过 promise。该值和相关延迟(以毫秒为单位)来自两个不同的 arrays。

As for the provided example code the expected behavior is a logging sequence where, one after the other and waiting for one another, each value from the target array gets logged with its related (same index) delay from the timeArray until the end of the target array's iteration.至于提供的示例代码,预期的行为是一个记录序列,其中一个接一个地等待另一个, target数组中的每个value都被记录下来,并记录了从timeArraytarget结束的相关(相同索引) delay数组的迭代。

I tried using the code shown below but it only prints out the first 2 elements in the timeArray but it doesn't print all of the other elements and I'm not sure if it's printing them after the first two time intervals in timeArray我尝试使用下面显示的代码,但它只打印出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();
  }
}());

For each step towards a generator for deferred values the OP could implement an own task... like...对于延迟值生成器的每一步,OP 都可以实现自己的任务……比如……

  • mapping both of the OP's arrays into a better processable data-structure... here an array of tuples where each tuple is made of... [<value>, <delay>] .将两个 OP 的 arrays 映射到一个更好的可处理数据结构中......这里是一个元组数组,其中每个元组由...... [<value>, <delay>]组成。

  • mapping of each value-delay tuple into a deferred value action which is an async function that creates and returns a promise which will resolve the value after the milliseconds delay where the mapping function that creates the async function is called createDeferredValue .将每个值延迟元组映射到延迟值操作,这是一个异步 function,它创建并返回一个 promise,它将在毫秒delay后解析value ,其中创建异步 function 的映射 function 称为createDeferredValue

  • creating the async generator from the array of async functions where the generator function is called createPoolOfDeferredValues .从异步函数数组创建异步生成器,其中生成器 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; }

But of cause, once having created the list/array of async functions, one can iterate it directly with for...await without the detour of an async generator.但是当然,一旦创建了异步函数的列表/数组,就可以直接使用for...await对其进行迭代,而无需绕过异步生成器。 Thus the above provided code simplifies to...因此,上面提供的代码简化为......

 // - 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; }

You created the generator with let generator = generateSequence() , but then you never iterated over it.您使用let generator = generateSequence()创建了生成器,但您从未对其进行迭代。

(This is spread out and uses more variable names, so it's easier to read): (这是分散的,使用了更多的变量名,所以更容易阅读):

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
        )
    })
}

This would be easier without generators:如果没有生成器,这会更容易:


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