Is there a better way to iterate over the results of a generator, my for loop is ugly:
for(let job = readyJob.next(); !job.done; job = readyJob.next()){ }
In context there is a generator function that can determine if there is a batch of work, consisting of 1..* jobs (the generator may also return no jobs in the batch). There is a continuous loop that instantiates the generator and iterates over the batch doing work on the job (logging).
Is there a more elegant solution to this iteration problem. I mean this looks like a traditional iterator from Java/C# which isn't bad. Something like an "each" would be super readable... That's my hope anyhow.
let getReadyJob = function *(instance){
let numJobs = 7 ; // getRandomInt(0, 10) ;
for(let i = 0; i < numJobs; i++) {
yield {
jobId: '' + instance + '::' + i,
jobReadyOn: (new Date()).valueOf()
};
}
}
then
while(true){
let readyJob = getReadyJob()
for(let job = readyJob.next(); !job.done; job = readyJob.next()){
console.log(JSON.stringify(job.value)) ;
}
}
You need to call next() or loop through the generator object to access the values produced by the generator expression. When there isn't the next value in the generator object, a StopIteration exception is thrown. A for loop can be used to iterate the generator object.
Simply speaking, a generator is a function that returns an object (iterator) which we can iterate over (one value at a time).
A return statement in a generator, when executed, will make the generator finish (i.e. the done property of the object returned by it will be set to true ). If a value is returned, it will be set as the value property of the object returned by the generator.
The yield* expression is used to delegate to another generator or iterable object.
Yes, if your environment already supports for...of
:
for (var job of readyJob) {
// ...
}
If not, have seen this a couple of times:
var next;
while (!(next = readyJob.next()).done) {
var job = next.value;
// ...
}
for ... of
is the elegant solution but not overall supported, however while (!(next = cursor.next()).done) {
is a very cryptic, and one might ask himself, how come (var x = someFunctionCall())
is evaluated to true
and
another would answer welcome to javascript
.
For that reason and to and give the answer another shape, it can also be done using a recursive function.
function loopThose(items) {
const item = items.next();
// doStuff(item);
if (!item.done) {
loopThose(items);
}
}
A true benefit is when async, try catch and custom continue condition come into play:
async function printKeys(items) {
try {
const item = await items.next();
// doStuff(item);
if (isConditionFulfil(item)) {
await this.printKeys(items);
}
} catch (e){
}
}
Where a generator function yields promises that might fail:
function * list(){
for (var i = 0; i<10; i++){
yield fetch(buildResourceUrl(i)).then(res => res.json())
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With