Я пытаюсь написать функцию, которая будет повторно вводить трассировку стека, когда брошен литерал объекта. (См. Этот связанный вопрос).
Я заметил, что если передать асинхронную функцию в качестве обратного вызова в другую асинхронную функцию вызывающего абонента, если вызывающая функция имеет функцию try/catch, перехватывает любые ошибки и выдает новую ошибку, трассировка стека теряется.
Я пробовал несколько вариантов этого:
function alpha() {
throw Error("I am an error!");
}
function alphaObectLiberal() {
throw "I am an object literal!"; //Ordinarily this will cause the stack trace to be lost.
}
function syncFunctionCaller(fn) {
return fn();
}
function syncFunctionCaller2(fn) { //This wrapper wraps it in a proper error and subsequently preserves the stack trace.
try {
return fn();
} catch (err) {
throw new Error(err); //Stack trace is preserved when it is synchronous.
}
}
async function asyncAlpha() {
throw Error("I am also an error!"); //Stack trace is preseved if a proper error is thown from callback
}
async function asyncAlphaObjectLiteral() {
throw "I am an object literal!"; //I want to catch this, and convert it to a proper Error object.
}
async function asyncFunctionCaller(fn) {
return await fn();
}
async function asyncFunctionCaller2(fn) {
try {
await fn();
} catch (err) {
throw new Error(err);
}
}
async function asyncFunctionCaller3(fn) {
try {
await fn();
} catch (err) {
throw new Error("I'm an error thrown from the function caller!");
}
}
async function asyncFunctionCaller4(fn) {
throw new Error("No try catch here!");
}
async function everything() {
try {
syncFunctionCaller(alpha);
} catch (err) {
console.log(err);
}
try {
syncFunctionCaller2(alphaObectLiberal);
} catch (err) {
console.log(err);
}
try {
await asyncFunctionCaller(asyncAlpha);
} catch (err) {
console.log(err);
}
try {
await asyncFunctionCaller2(asyncAlphaObjectLiteral);
} catch (err) {
console.log(err); //We've lost the 'everthing' line number from the stack trace
}
try {
await asyncFunctionCaller3(asyncAlphaObjectLiteral);
} catch (err) {
console.log(err); //We've lost the 'everthing' line number from the stack trace
}
try {
await asyncFunctionCaller4(asyncAlphaObjectLiteral);
} catch (err) {
console.log(err); //This one is fine
}
}
everything();
Вывод: запишите мои комментарии в трассировке стека
[nodemon] starting 'node src/index.js localhost 8080'
Error: I am an error!
at alpha (/sandbox/src/index.js:2:9)
at syncFunctionCaller (/sandbox/src/index.js:6:10)
at everything (/sandbox/src/index.js:43:5)
//We can see what function caused this error
at Object.<anonymous> (/sandbox/src/index.js:73:1)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)
Error: I am an object literal!
at syncFunctionCaller2 (/sandbox/src/index.js:17:11)
at everything (/sandbox/src/index.js:65:5)
//In a synchronous wrapper, the stack trace is preserved
at Object.<anonymous> (/sandbox/src/index.js:95:1)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)
at startup (internal/bootstrap/node.js:283:19)
Error: I am also an error!
at asyncAlpha (/sandbox/src/index.js:10:9)
at asyncFunctionCaller (/sandbox/src/index.js:18:16)
at everything (/sandbox/src/index.js:49:11)
//We can see what function caused this error
at Object.<anonymous> (/sandbox/src/index.js:73:1)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)
Error: I am an object literal!
at asyncFunctionCaller2 (/sandbox/src/index.js:25:11)
//We've lost the stacktrace in 'everything'
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:832:11)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
Error: I'm an error thrown from the function caller!
at asyncFunctionCaller3 (/sandbox/src/index.js:33:11)
//We've lost the stacktrace in 'everything'
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:832:11)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
Error: No try catch here!
at asyncFunctionCaller4 (/sandbox/src/index.js:38:9)
at everything (/sandbox/src/index.js:67:11)
//We can see what function caused this error
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:832:11)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
[nodemon] clean exit - waiting for changes before restart
Мне кажется, что это все испортит утверждение await.
Что здесь происходит?