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')
}