ES6生成器:来自iterator.throw的错误堆栈跟踪(错误)

Ava*_*che 18 javascript ajax yield generator ecmascript-6

ES-6 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
}
Run Code Online (Sandbox Code Playgroud)

虽然这个问题不是特定的Promises,但它们可能更容易描述问题.就我而言,我正在使用具有生成器和承诺的任务系统.假设函数ajax()返回Promise,如果拒绝,则使用此机制将错误转换为yield语句中的throw.

调试器中的堆栈跟踪非常无用,因为我找不到获取yield statement此注入发生位置的函数,文件或行号的方法.调用iterator.throw(err)被视为重新抛出,并且不会获得新的堆栈信息,因此它只显示ajax()函数内部可以从许多地方调用的位置,并且通过outer()像上面的示例中那样抛出新错误,相同的抛出线显示对于所有错误.两者都没有给出generator关于调试错误所执行的函数的提示.


我使用的是Chrome v42.

Kei*_*ith 1

迭代器和 Promise 还不能很好地混合——你本质上是在产生一个 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);
}
Run Code Online (Sandbox Code Playgroud)

只是:无论如何,这就是“什么”asyncawait“做什么”(这些关键字只是用于返回结果的承诺生成器的语法糖),如果您使用它们,则常规try-catch将起作用。

iterator.throw主要是一种停止迭代的方法,而不是将异常注入回迭代中 - 堆栈顶部仍然是您创建Error.

最后,Chrome 中即将推出的是异步迭代器——它们非常强大,并且都是关于 Promise 的迭代。