手动错误出 ReadableStream 或 TransformStream 会导致错误被记录为未捕获的错误

Manually erroring out a ReadableStream or TransformStream causes the error to be logged as an uncaught error

当使用 Error 对象调用 ReadableStreamDefaultController.errorTransformStreamDefaultController.error 以手动错误输出流时,错误将在调用站点的浏览器控制台中记录为未捕获错误,如如果 .error() 方法本身重新抛出它收到的错误。

以下带有 ReadableStream 源和 WritableStream 目标的简短片段展示了这个问题,但是,Whosebug 片段控制台似乎无法记录错误(检查浏览器控制台,在 Chrome 80):

let sourceController;
let source = new ReadableStream({
    start: (controller) => {
        sourceController = controller;
    }
});

let destination = new WritableStream({
    start: () => {
     // ...
    },
    abort: (reason) => {
     console.log("aborted:");
        console.log(reason);
    }
});

source.pipeTo(destination);
window.setTimeout(() => sourceController.error(new Error("wut?")), 1000);
//                                       ^^^^^
//                                       js:30 Uncaught (in promise) Error: wut?

从错误消息来看,这可能是某处被拒绝的承诺,但我不知道在哪里。奇怪的是,尝试使用以下侦听器观察此未捕获的错误也没有任何效果:

window.onerror = (e) => console.error(e); // Never gets called

我会想在目标 WritableStream 上定义 abort 方法标记流已启用错误处理,但错误仍然记录为未捕获的错误(奇怪的是,abort方法同时调用)。

对我来说,这个错误似乎是完全无害的,但确实很烦人。

我如何摆脱它? 在这个东西周围添加一个 try ... catch 没有任何作用。

错误源自 pipeTo 调用返回的 Promise,因为错误输出流将 拒绝 此 Promise。解决方法是添加缺失的catch子句:

source.pipeTo(destination).catch(err => ...)

或者,在 async 执行上下文中:

try {
    await source.pipeTo(destination);
} catch (err) {
    ...
}

这在WHATWG Streams spec中有解释:

An error in the source readable stream will abort the destination writable stream, unless preventAbort is truthy. The returned promise will be rejected with the source’s error, or with any error that occurs during aborting the destination.