Javascript 为什么新承诺的reject()会在可怕的“中丢失堆栈跟踪”;未兑现的(承诺中的)“;错误
在Angular的github发行版中搜索“Uncaught(in promise)”,google或stackoverflow上的此处会产生很多非常具体的结果,但我的问题要宽泛一些(由于结果激增,我不知道这是否是重复) 前提:在我的代码中的某个地方,我有一个未预料到的拒绝承诺(Angular 4.4.4) 案例: 案例1:简单拒绝 在MyComponent中: 在控制台中产生这个(很好,我可以看到它来自哪里): 案例2:新承诺,抛出错误 在MyComponent中: 在控制台中产生这种效果(更好的是,在现场给出位置): 这也适用于链接,例如,以下内容在控制台中或多或少给出了相同的堆栈跟踪Javascript 为什么新承诺的reject()会在可怕的“中丢失堆栈跟踪”;未兑现的(承诺中的)“;错误,javascript,angular,es6-promise,Javascript,Angular,Es6 Promise,在Angular的github发行版中搜索“Uncaught(in promise)”,google或stackoverflow上的此处会产生很多非常具体的结果,但我的问题要宽泛一些(由于结果激增,我不知道这是否是重复) 前提:在我的代码中的某个地方,我有一个未预料到的拒绝承诺(Angular 4.4.4) 案例: 案例1:简单拒绝 在MyComponent中: 在控制台中产生这个(很好,我可以看到它来自哪里): 案例2:新承诺,抛出错误 在MyComponent中: 在控制台中产生这种效果(更
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:使用拒绝(…)
在MyComponent中:
更改使用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>
core.es5.js:1020错误:未捕获(承诺中):baz
在resolvePromise(zone.js:824)
在resolvePromise(zone.js:795)
在zone.js:873
在ZoneDelegate.webpackJsonp…/../../../../../../zone.js/zone.js.ZoneDelegate.invokeTask(zone.js:425)
位于Object.onInvokeTask(core.es5.js:3881)
在ZoneDelegate.webpackJsonp…/../../../../../../zone.js/zone.js.ZoneDelegate.invokeTask(zone.js:424)
位于Zone.webpackJsonp…/../../../../../Zone.js/dist/Zone.js.Zone.runTask(Zone.js:192)
在drainMicroTaskQueue(zone.js:602)
在
问题
部分回答了我自己的一个问题: 如果我将案例#3改为:(包装在新的错误对象中) 然后,令人惊讶的是,我确实得到了堆栈跟踪!(仅构造错误即可保存堆栈跟踪) 顺便说一句。。。既然(我猜)我们大多数人都喜欢看堆栈跟踪而不是不看,那么为什么这里没有提到这是一个最佳实践呢 编辑 为了确保我不会忘记,我添加了这个缩小(
reject:(原因:Error)=>void
而不是any
),不确定这是否是一个很好的解决方案,因为它不能防止传递any
,但它可以帮助保护一些不传递错误的情况
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>;
}
}
export{}
宣布全球{
接口承诺构造函数{
/**
*对原型的引用。
*/
只读原型:Promise;
/**
*创造新的承诺。
*@param executor用于初始化承诺的回调。此回调传递了两个参数:
*使用值或其他承诺的结果解析承诺时使用的解析回调,
*以及拒绝回调,用于以提供的原因或错误拒绝承诺。
*/
新(执行人:(决定:(价值?:T |承诺)=>无效,拒绝:(原因:错误)=>无效)=>无效):承诺;
}
}
尝试拒绝(新错误(“foo”)
。您使用的承诺实现是什么?关于问题2:Oops,没有看到@Bergi的评论中说的正是这一点。保持清晰。。。
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));
}
ngOnInit() {
new Promise((resolve, reject) => {
reject("foo");
}).then(() => {
console.log("ain't gonna happen");
});
}
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>
ngOnInit() {
new Promise((resolve, reject) => {
reject(new Error("foo"));
}).then(() => {
console.log("ain't gonna happen");
});
}
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>;
}
}