gpt4 book ai didi

javascript - 为什么新 Promise 的 reject() 会在可怕的 "Uncaught (in promise)"错误中丢失堆栈跟踪

转载 作者:太空狗 更新时间:2023-10-29 18:01:19 25 4
gpt4 key购买 nike

在 Angular 的 github issues、google 或 here on stackoverflow 中搜索“Uncaught (in promise)”会产生很多非常具体的结果,但我的问题有点宽泛(而且由于结果激增,我不知道这是否重复)

前提:在我的代码中某处我有一个未捕获的 promise 拒绝(Angular 4.4.4)

案例:

案例一:简单拒绝

在我的组件中:

ngOnInit() {
Promise.reject("foo");
}

在控制台中产生这个(很好,我可以看到它来自哪里):

ERROR Error: Uncaught (in promise): foo
at resolvePromise (zone.js:824)
at Function.ZoneAwarePromise.reject (zone.js:903)
at MyComponent.webpackJsonp.../../../../../src/app/component/my.component.ts.MyComponent.ngOnInit (my.component.ts:nn)

案例二:新建Promise,抛出错误

在我的组件中:

ngOnInit() {
new Promise((resolve, reject) => {
throw new Error("foo");
}).then(() => {
console.log("ain't gonna happen");
});
}

在控制台中生成这个(更好的是,当场给出位置):

ERROR Error: Uncaught (in promise): Error: foo
Error: foo
at my.component.ts:nn
at new ZoneAwarePromise (zone.js:890)
at MyComponent.webpackJsonp.../../../../../src/app/component/my.component.ts.LMyComponent.ngOnInit (my.component.ts:nn)

这也适用于链接,例如以下在控制台中或多或少地给出了相同的堆栈跟踪。

ngOnInit() {


const promise3 = new Promise((resolve, reject) => {
throw new Error("baz");
});
const promise2 = new Promise((resolve, reject) => {
resolve(promise3);
});

const promise1 = new Promise((resolve, reject) => {
resolve(promise2);
});

promise1.then(p1=> console.log(p1));
}

案例 3:使用 reject(...)

在我的组件中:

ngOnInit() {
new Promise((resolve, reject) => {
reject("foo");
}).then(() => {
console.log("ain't gonna happen");
});
}

将抛出错误更改为使用 promise 的 reject 方法(我认为这是很常见的做法),会产生这种恐怖:

core.es5.js:1020 ERROR Error: Uncaught (in promise): baz
at resolvePromise (zone.js:824)
at resolvePromise (zone.js:795)
at zone.js:873
at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425)
at Object.onInvokeTask (core.es5.js:3881)
at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:424)
at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask (zone.js:192)
at drainMicroTaskQueue (zone.js:602)
at <anonymous>

问题

  1. 为什么这次我看不到堆栈跟踪或错误来源? (我假设这是因为 JavaScript 仅从抛出错误的位置生成堆栈跟踪?)

  2. 如果是这样,使用显式拒绝而不是在新 Promise 中抛出新错误是否是一种不好的做法?它是否记录在某处而我错过了?

  3. 有什么办法可以解决这个问题吗? (获取堆栈跟踪并继续使用 reject(...) 而不是抛出错误?我假设不会)

  4. 这是一个众所周知的问题/不良做法吗,我只是错过了备忘录?

最佳答案

部分回答我自己的问题之一:

如果我将案例 #3 更改为:(包装在一个新的 Error 对象中)

ngOnInit() {
new Promise((resolve, reject) => {
reject(new Error("foo"));
}).then(() => {
console.log("ain't gonna happen");
});
}

然后,令人惊讶的是,我确实得到了堆栈跟踪! (仅仅构造一个错误就可以保存堆栈跟踪)

旁注...因为(我猜)我们大多数人更喜欢看到堆栈跟踪而不是不看到,那么为什么哦为什么这里没有将其作为最佳实践提及?:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

编辑

为了确保我不会忘记,我添加了这个缩小(reject: (reason: Error) => void 而不是 any),不确定这是否是一个很好的解决方案,因为它不能防止传递 any,但它可以帮助防止某些情况下不传递 Error 以拒绝。

export {}

declare global {

interface PromiseConstructor {
/**
* A reference to the prototype.
*/
readonly prototype: Promise<any>;

/**
* Creates a new Promise.
* @param executor A callback used to initialize the promise. This callback is passed two arguments:
* a resolve callback used resolve the promise with a value or the result of another promise,
* and a reject callback used to reject the promise with a provided reason or error.
*/
new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason: Error) => void) => void): Promise<T>;

}
}

关于javascript - 为什么新 Promise 的 reject() 会在可怕的 "Uncaught (in promise)"错误中丢失堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46830568/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com