ES6生成器:来自iterator.throw的错误堆栈跟踪(错误)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6生成器:来自iterator.throw的错误堆栈跟踪(错误)相关的知识,希望对你有一定的参考价值。
ES6方法:iterator.throw(err)
通常被描述为注入异常,就好像它发生在生成器中的yield
语句中一样。问题是此异常的堆栈跟踪不包含对yield语句的文件/行的任何引用,甚至不包含它所在的函数。相反,堆栈跟踪似乎只在构造异常对象时生成,这不在generator
内。
问题是:如何在堆栈跟踪中获取有问题的yield语句的位置?
function* one_of_many_generators() {
// ...
yield ajax(url); // <-- what I need in the stack trace
// ...
}
function outer() {
var iterator = one_of_many_generators();
iterator.next(); // runs to the first yield
// inject exception at the yield statement
iterator.throw(Error("error")); // <-- top of stack trace shows here
}
虽然这个问题不是Promises
特有的,但它们可能会更容易描述问题。就我而言,我正在使用具有生成器和承诺的任务系统。假设函数ajax()
返回一个Promise,如果拒绝,则使用此机制将错误转换为yield语句中的throw。
调试器中的堆栈跟踪非常无用,因为我无法找到发生此注入的yield statement
的函数,文件或行号。调用iterator.throw(err)
被视为重新抛出,并且不会获得新的堆栈信息,因此它只显示ajax()
函数内部的位置,可以从许多地方调用,并在outer()
中抛出一个新错误,如上例所示,同样抛出线显示所有错误。两者都没有给出关于为调试错误执行generator
函数的提示。
我使用的是Chrome v42。
迭代器和承诺混合得不是很好(但是) - 你基本上会产生一个在循环之外失败的承诺。
你可以通过将promise的结果传递回生成器来解决这个问题,例如:
function* one_of_many_generators() {
// ...
var promiseResult = yield ajax(url); // <-- what I need in the stack trace
// Now we're back in the generator with the result of the promise
if(notHappyWithResult(promiseResult))
throw new Error('Reason result is bad');
// ...
}
async function outer() {
var iterator = one_of_many_generators();
let prms = iterator.next(); // runs to the first yield
// Wait for the promise to finish
let result = await prms;
// Pass the result back to the generator
let whatever = iterator.next(result);
}
只有:这就像async
和await
所做的那样(这些关键词只是一个承诺生成器的语法糖,结果被传回)如果你使用它们,常规try-catch
将起作用。
iterator.throw
主要是一种停止迭代的方法,而不是将异常注入其中 - 堆栈的顶部仍然是你创建Error
的地方。
最后,Chrome即将推出的是async iterators - 这些非常强大,而且都是关于承诺的迭代。
这种方法怎么样:
async function example() {
const arrayOfFetchPromises = [
fetch('1.txt'),
fetch('2.txt'),
fetch('3.txt')
];
// Regular iterator:
for (const item of arrayOfFetchPromises) {
console.log(item); // Logs a promise
}
// Async iterator:
for await (const item of arrayOfFetchPromises) {
console.log(item); // Logs a response
}
}
在这种情况下,for-await
从array
获取每个项目并等待它解决。即使第二个响应尚未准备好,您也会得到第一个响应,但是您将始终以正确的顺序获得响应。您可以简单地处理拒绝,例如使用相同的旧.catch
:)但是已知这种模式容易出现未处理的拒绝。总是有Promise.all
... Promise.all版本是:
const [value1, value2] = await Promise.all([getValue1Async(), getValue2Async()]);
我还建议查看一些这些工具:iter-tools
以上是关于ES6生成器:来自iterator.throw的错误堆栈跟踪(错误)的主要内容,如果未能解决你的问题,请参考以下文章