如何迭代生成器函数的结果

11

有没有更好的方式来遍历生成器的结果,我的for循环看起来很丑陋:

for(let job = readyJob.next(); !job.done; job = readyJob.next()){ } 

在这个场景中,有一个生成器函数,可以确定是否存在由1..*个作业组成的工作批次(生成器也可能不返回批次中的任何作业)。有一个连续的循环,实例化生成器并迭代处理作业批次(记录日志)。

这个迭代问题是否有更优雅的解决方案?我的意思是,这看起来像是来自Java/C#的传统迭代器,这并不是不好。类似于“each”的东西会更易读... 这是我希望的。

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

然后

while(true){
    let readyJob = getReadyJob()

    for(let job = readyJob.next(); !job.done; job = readyJob.next()){
        console.log(JSON.stringify(job.value)) ;
    }
}
2个回答

23

如果您的环境已经支持 for...of,那么是可以的:

for (var job of readyJob) {
  // ...
}

如果没有的话,我见过几次这种情况:

var next;
while (!(next = readyJob.next()).done) {
   var job = next.value;
   // ...
}

1
"For of"正是我一直在寻找的(开个玩笑) - 谢谢。我认为“while循环”选项应该与我提到的“for循环”选项放在一起,并且非常类似于C++/Java/C# - 当然它可以工作,但这一行上有太多事情发生了,而且不是特别易读... - akaphenom
嗯,“while”是相当惯用的。但是就可读性而言,“for..of”更胜一筹 - 并且与生成器完美搭配。 - raina77ow
1
迭代时使用索引怎么样? - Weilory
1
@Weilory:只需保留自己的计数器。 - Felix Kling

2

for ... of 是一种优雅的解决方案,但不是全面支持的,然而 while (!(next = cursor.next()).done) { 很难理解,有人可能会问自己,为什么 (var x = someFunctionCall()) 被评估为 true,另一个人会回答 welcome to javascript

因此,为了给出另一种答案,也可以使用递归函数。

function loopThose(items) {
    const item = items.next();

    // doStuff(item);

    if (!item.done) {
        loopThose(items);
    }
}

一个真正的好处是当异步、try catch 和自定义继续条件发挥作用时:
async function printKeys(items) {
    try {
       const item = await items.next();
       // doStuff(item);
       if (isConditionFulfil(item)) {
          await this.printKeys(items);
       }
    } catch (e){

    }
}

如果生成器函数产生可能失败的承诺:

function * list(){
  for (var i = 0; i<10; i++){
     yield fetch(buildResourceUrl(i)).then(res => res.json())
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接