Javascript 在生成器内部抛出的错误将完成它,尽管被捕获

Javascript 在生成器内部抛出的错误将完成它,尽管被捕获,javascript,error-handling,generator,Javascript,Error Handling,Generator,我有一个异步生成器函数,它在内部调用一些可能引发错误的异步函数。我想要的是,当错误发生时,生成器只记录它,然后继续进一步工作。所以我有一个这样的代码 async * getAll (somestuff) { try { const thing = await fetchThing() const otherThing = await fetchAnother() yield { ...thing, ...otherThing }

我有一个异步生成器函数,它在内部调用一些可能引发错误的异步函数。我想要的是,当错误发生时,生成器只记录它,然后继续进一步工作。所以我有一个这样的代码

async * getAll (somestuff) {
  try {
    const thing = await fetchThing()
    const otherThing = await fetchAnother()

    yield {
      ...thing,
      ...otherThing
    }
  } catch (error) {
    console.log('Error happened, but thats ok, I want to continue')
  }
}
但当错误发生时,catch块会记录它,但生成器会生成{done:true},操作停止。 我曾尝试在console.log进入catch块后手动生成null,但结果相同。

这种“问题”与生成器本身无关,它只是与
try..catch块内的
wait
机制有关,因为每当try-catch块内拒绝承诺时,
捕获
被加入
(除非承诺被单独捕获)

事实上,生成器不能再进一步,因为一旦以某种方式到达
捕获
,它将继续,直到调用另一个
产量
。如果不需要调用任何函数,它只需给出
done:true
,这就是生成器的预期行为

您的主要问题是,您希望生成器生成所有的值,但它不能,因为
生成块从未达到:

try {
    const thing = await fetchThing()
    const otherThing = await fetchAnother()

    yield { // <-- never met if either thing or otherThing are rejected.
      ...thing,
      ...otherThing
    }
  } catch (error) { // <-- this block is reached whenever either thing or otherThing raise an exception.
    console.log('Error happened, but thats ok, I want to continue')
  }
这样,无论两者都失败还是都将成功,都将到达
yield
块并继续执行

下面是一个例子,展示了上述内容:

const fakeAsync=async()=>wait Promise.resolve(true);
const fakeAsyncReject=async()=>wait Promise.reject(false);
异步函数*getAll(someStuff){
试一试{
让res,raiseExc;
试一试{
res=等待fakeAsync();
}
捕获(内部重新异常){
log('引发内部异常');
}
试一试{
raiseExc=wait fakeAsyncReject();
}
捕获(innerRaiseException){
log('引发了内部异常',innerRaiseException);
}
//除非这个try块中有什么真正的错误,比如语法错误或者其他什么。
屈服{
物件,
raiseExc
}
}
捕获(错误){
//仅当上面的try块产生异常时才会引发catch块,而当try-catch内的try-catch块实际加入catch时不会引发catch块。
log('发生错误',错误);
}
}
//如果要查看for await的工作方式,请取消对该块的注释。
/*
(异步()=>{
对于等待(getAll([])的var res){
console.log('res is',res);
}
})();
*/
(异步()=>{
常量asyncIterator=getAll([]);
log(等待asyncIterator.next());

})();除了try-catch之外,生成器没有其他要做的事情。。。你期待什么?最后它似乎起作用了,我需要仔细考虑一下,再多读一些。非常感谢您的解释@briosheje!还有一件事,如果代码需要到达yield关键字才能继续,我想知道为什么catch(){yield null}不起作用?不客气,请记住,每个未处理的承诺拒绝都会导致这种行为,因此即使循环一组承诺,也应该处理它;)。不过,希望这能让事情变得清楚。
try {
    let thing, otherThing;
    try {
       thing = await fetchThing()
       otherThing = await fetchAnother()
    }
    catch (innerException) {
       console.log('either of the above failed!', innerException);
    }
    // in this way, the below block will be reached.
    yield {
      ...thing,
      ...otherThing
    }
  } catch (error) {
    console.log('Error happened, but thats ok, I want to continue')
  }