I've stumbled upon an issue similar to the one discussed in this question but does not seem to be the same. I have a function returning a promise and rejecting (in case of errors) after a while (it's doing an HTTP call, so it takes some time). While the request is flying around the internet Node takes care of other instructions, when the request is received and the error thrown the stack trace begins from processTicksAndRejections
(as it would for any async operations, I guess). This is a problem as I no longer have a record of where the function was called from.
So I tried the following approach, the normal code would be
const fetch = require('node-fetch');
function myFunction() {
return new Promise(async (resolve, reject) => {
fetch('https://www.google.com').then(() => {
return reject(new Error('Whoops!'));
});
});
}
myFunction().catch(console.log);
which prints out
Error: Whoops!
at /home/dami/projects/testing/stack.js:8:21
at processTicksAndRejections (internal/process/task_queues.js:95:5)
The idea is to concatenate the old stack trace like
function myFunction() {
const stack = (new Error()).stack;
return new Promise(async (resolve, reject) => {
fetch('https://www.google.com').then(() => {
const error = new Error('Test');
error.stack = stack;
reject(error);
});
});
}
myFunction().catch(console.log);
which prints
Error: Test
at /home/dami/projects/testing/stack.js:8:21
at processTicksAndRejections (internal/process/task_queues.js:95:5)Error
at myFunction (/home/dami/projects/testing/stack.js:4:18)
at a (/home/dami/projects/testing/stack.js:16:3)
at Object.<anonymous> (/home/dami/projects/testing/stack.js:19:1)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
at internal/main/run_main_module.js:17:47
However, this does not seem the best (and most neat) solution to me, as at this point I have two 'sources' of the trace (one being the normal Node process at run_main_module, the other at processTicksAndRejections).
So the final question, is there a best practice approach to this problem? I've tried using async/await and keeping the rejection at the top level of myFunction
, but it will always be picked up by processTicksAndRejections
because of its async nature. Thanks!
CodePudding user response:
I would use an async function here exactly for the reason of preserving the stack trace:
async function myFunction() {
await fetch('https://www.google.com');
throw new Error('Whoops!');
}
async function foo() {
await myFunction();
}
async function bar() {
await foo();
}
bar().catch(console.log);
Don't be bothered by the process.processTicksAndRejections
entry in the stack trace. As long as async/await are used consistently, the whole call chain should be logged with the exception.