我试图了解如何从setTimeout
我正在运行以下示例:
'use strict';
function main() {
f1().catch(e => {
console.error('got error with trace:');
console.error(e);
});
f2().catch(e => {
console.error('got error with trace:');
console.error(e);
});
}
async function f1() {
return new Promise((resolve, reject) => {
reject(new Error('Error in normal flow'));
});
}
async function f2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Error in timeout'));
}, 0);
});
}
main();
我得到了这个输出:
got error with trace:
Error: Error in normal flow
at Promise (/Users/me/project/example.js:25:12)
at Promise (<anonymous>)
at f2 (/Users/me/project/example.js:24:10)
at main (/Users/me/project/example.js:9:3)
at Object.<anonymous> (/Users/me/project/example.js:29:1)
at Module._compile (module.js:569:30)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:503:32)
at tryModuleLoad (module.js:466:12)
at Function.Module._load (module.js:458:3)
got error with trace:
Error: Error in timeout
at Timeout.setTimeout [as _onTimeout] (/Users/me/project/example.js:18:14)
at ontimeout (timers.js:488:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:283:5)
如何使用setTimeout启动的承诺的堆栈跟踪更加详细,就像没有setTimeout
的承诺一样?
当我在实际生产代码中发生这种情况时,我无法确切地知道错误的起源。这使得调试非常困难。
答案 0 :(得分:0)
之前我做过类似的事情:
async function f2() {
return new Promise((resolve, reject) => {
const potentialError = new Error('Error in timeout');
setTimeout(() => {
reject(potentialError);
}, 0);
});
}
这会导致错误,就像setTimeout
之外的错误一样。无论你在哪里创建错误,都会决定你的堆栈跟踪。
对我来说,一个用例是一个超时的测试,因为承诺永远不会解决(在我的情况下,使用puppeteer和mocha / jasmine)。因为超时没有有意义的堆栈跟踪,所以我写了a wrapper around the promise that includes a setTimeout
,就像这个例子一样。
答案 1 :(得分:0)
我试着这样写:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
FilterAdministratorToken=dword:0
尽量避免在非承诺回调中做任何事情。
答案 2 :(得分:0)
这里有一些不错的答案,但是尚未考虑的事情是生成堆栈跟踪非常昂贵,并且您不想一直这样做。 V8有一个出色的JIT编译器,该编译器可能会无序运行,并且必须解绕才能获得正确的堆栈跟踪。因此,只有在需要时,我们才应该为“潜在错误”生成堆栈跟踪。
async function f2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
// Stack trace is unhelpful here.
reject(new Error("Error in timeout"))
}, 0)
})
}
async function f3() {
// This stack trace is useful here, but generating a stack trace is expensive
// because V8 has to unravel all of its fancy JIT stuff.
const potentialError = new Error("Error in timeout")
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(potentialError)
}, 0)
})
}
async function f4() {
try {
const result = await new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Error in timeout"))
}, 0)
})
return result
} catch (error) {
// Override the stack trace only when you need it.
error.stack = new Error().stack
throw error
}
}