ES6生成器:从iterator.throw(err)中跟踪堆栈错误
ES6 Generators: poor stack trace from iterator.throw(err)
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,如果该Promise被拒绝,则使用此机制将错误转换为yield语句的throw。
调试器中的堆栈跟踪是非常无用的,因为我找不到一种方法来获得 yield statement
的函数、文件或行号,该注入发生在那里。调用iterator.throw(err)
被视为重新抛出,并且不会获得新的堆栈信息,因此它只显示ajax()
函数内部可以从许多地方调用的位置,并且通过在outer()
中抛出一个新的错误,就像上面的例子一样,相同的抛出行显示所有错误。两者都没有给出关于调试错误时正在执行的generator
函数的提示。
我使用Chrome v42
迭代器和承诺器还不能很好地混合在一起——你实际上是在生成一个承诺,然后在循环外失败。
你可以通过将承诺的结果传递回生成器来绕过这个问题,比如:
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);
}
Only:这就是async
和await
所做的事情(这些关键字只是承诺生成器的语法糖,返回结果),如果你使用它们,一个常规的try-catch
也可以工作。
iterator.throw
主要是一种停止迭代的方式,而不是向它注入异常——堆栈的顶部仍然是你创建Error
的地方。
最后,即将在Chrome中出现的是async迭代器-这些非常强大,都是关于承诺的迭代。
这个方法怎么样:
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
…的承诺。所有版本为:
const [value1, value2] = await Promise.all([getValue1Async(), getValue2Async()]);
我还建议您查看以下一些工具:
- 动态分配GA增强型电子商务跟踪器
- 跟踪在页面加载时应用内联样式的JavaScript
- 跟踪用户点击Adsense广告的IP地址
- 跟踪jqplot垂直折线图的鼠标位置
- 点击facebook像素跟踪注册(JS/JQUERY代码)
- 有没有一种方法可以从URL跟踪请求的域
- Javascript-在视频中跟踪鼠标位置
- 在Google Analytics中跟踪用户,但只能在两个操作之间跟踪
- 如何使用Google Analytics跟踪表单提交
- Fresh Spark Install+Homestead上的Vue异步堆栈跟踪错误
- 代码挑战:创建一个跟踪对象实例总数的类Foo
- 打印javascript控制台的堆栈跟踪
- 谷歌分析:如何跟踪移动网站的点击量作为对主网站的点击
- 即使光标位于屏幕边缘,也可以跟踪鼠标速度
- 什么'这是谷歌分析跟踪代码使用的技术
- 如何将Google Analytics配置为将URL参数作为单个页面进行跟踪
- 在不同的屏幕和分辨率上跟踪鼠标并将其关联起来
- 如何在jsoup的帮助下跟踪我的网站是否加载到android设备上
- Angular.js通过对象关键点上的ng选项进行跟踪
- ES6生成器:从iterator.throw(err)中跟踪堆栈错误