I'm trying to write a generator function which creates an async generator. 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.
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.
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
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();
}
}());
CodePudding user response:
You created the generator with let generator = generateSequence()
, but then you never iterated over it.
(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 );
}
CodePudding user response:
For each step towards a generator for deferred values the OP could implement an own task ... like ...
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>]
.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 millisecondsdelay
where the mapping function that creates the async function is calledcreateDeferredValue
.creating the async generator from the array of async functions where the generator function is called
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. 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; }