用于 ES6 生成器的 hasNext()

hasNext() for ES6 Generator

我将如何为生成器实现 hasNext() 方法。我尝试了很多选项,例如将生成器添加为 return 语句并从闭包中产生。获取第一个值打印它,然后使用 while 等,但其中 none 实际上有效。

我知道我可以像 那样使用 for of 或 while,但仍然想知道我是否可以添加 hasNext()。

function *range(start,end){

    while(start < end){
        yield start; 
        start++
    }
}

let iterator = range(1,10); 

// so I can do something like this. 
while(iterator.hasNext()){
   console.log(iterator.next().value); 
}

您可以通过检查 start + 1 < endrange 创建并 return 一个将 hasNext 定义为 Boolean 的对象;递归调用一个函数,hasNext 如果生成器 .next().donefalse 并且 generator.next().value 处的对象的 hasNext 属性 设置为 true , 否则执行其他任务

function* range(start, end) { 
  let next = () => start + 1 < end;
  let g = {
    hasNext: next(),
    currentValue: start
  };
  while (start < end) {
    yield g;
    g.currentValue = ++start;
    g.hasNext = next();
  }
}

let iterator = range(1, 10);

function hasNext(gen) {
  let curr = gen.next();
  if (!curr.done) {
    if (curr.value.hasNext) {
      console.log(`hasNext:${curr.value.hasNext}`
                 , `currentValue:${curr.value.currentValue}`);
      hasNext(gen);
    } else {
      console.log(JSON.stringify(curr.value, null, 2));
    }
  }
}

hasNext(iterator);

循环迭代器的简单非for…of方法是

for (let iterator = range(1, 10), r; !(r = iterator.next()).done; ) {
    console.log(r.value);
}

如果你真的想使用hasNext,你也可以这样做,但是有点奇怪:

const iterator = range(1, 10);
iterator.hasNext = function hasNext() {
    const r = this.next();
    this.current = r.value;
    return !r.done;
};
while (iterator.hasNext()) {
    console.log(iterator.current);
}

我创建了这个简单的模块。它允许您装饰任何迭代器并获取是否有更多元素的信息。

https://www.npmjs.com/package/iterable-has-next

用法就这么简单:

//...
const { extendIterator } = require('iterable-has-next')
const extendedIterator = await extendIterator(yourIterator)
while (extendedIterator.hasNext()) {
    const { value } = await extendedIterator.next()
    console.log(value)
}
//...

你可以试试看 https://repl.it/repls/YummyWrathfulRhombus

这是另一种选择。不使用生成器函数,而是创建一个常规函数并让它 return 一个具有 hasNext()next() 自定义实现的对象,并为 for...of 循环添加一个用户定义的可迭代对象:

function getRange(start, end) {
    return {
        hasNext() {
            return start <= end;
        },
        next() {
            return start <= end ? start++ : undefined;
        },
        *[Symbol.iterator]() {
            while(start <= end) yield start++;
        }
    };
}

console.log('Test iteration A');
let iteratorA = getRange(1, 10);

while(iteratorA.hasNext()) {
    console.log(iteratorA.next());
}


console.log('\n\nTest iteration B');
let iteratorB = getRange(20, 30);

for(let index of iteratorB) {
    console.log(index);
}