admin管理员组

文章数量:1425659

While rethrowing an Error of a rejected Promise, I noticed that the stack trace seem to be inplete.

For example:

// returns a Promise that is later on rejected.
function a() {
    return new Promise((resolve, reject)=>{
        setTimeout(()=>reject(new Error("a")), 2000);
    });
}

async function b() {
    await a();
}

async function c() {
    await b();
}

// testing
async function test() {
    let printError = (error)=>console.log(error.stack);

    await a().catch(printError);
    await b().catch(printError);
    await c().catch(printError);
}

test();

All three function calls in test() print the following:

Error: a
    at <anonymous>:4:31

I would have expected something like:

Error: a
    at <anonymous>:4:31
    at new Promise (<anonymous>)
    at a (<anonymous>:3:12)
    at b2 (<anonymous>:13:15)
    at c2 (<anonymous>:21:15)
    at test (<anonymous>:32:2)

Shouldn't the calling functions be part of the stack trace?



I tested this code in Google Chrome.

While rethrowing an Error of a rejected Promise, I noticed that the stack trace seem to be inplete.

For example:

// returns a Promise that is later on rejected.
function a() {
    return new Promise((resolve, reject)=>{
        setTimeout(()=>reject(new Error("a")), 2000);
    });
}

async function b() {
    await a();
}

async function c() {
    await b();
}

// testing
async function test() {
    let printError = (error)=>console.log(error.stack);

    await a().catch(printError);
    await b().catch(printError);
    await c().catch(printError);
}

test();

All three function calls in test() print the following:

Error: a
    at <anonymous>:4:31

I would have expected something like:

Error: a
    at <anonymous>:4:31
    at new Promise (<anonymous>)
    at a (<anonymous>:3:12)
    at b2 (<anonymous>:13:15)
    at c2 (<anonymous>:21:15)
    at test (<anonymous>:32:2)

Shouldn't the calling functions be part of the stack trace?



I tested this code in Google Chrome.

Share Improve this question edited Jan 22, 2022 at 16:46 AFoeee asked Jan 22, 2022 at 15:42 AFoeeeAFoeee 76110 silver badges25 bronze badges 2
  • 1 basically because it's called by setTimeout and not a – apple apple Commented Jan 22, 2022 at 15:59
  • it'd help to see if you name all those function. – apple apple Commented Jan 22, 2022 at 16:00
Add a ment  | 

2 Answers 2

Reset to default 7

Async stack traces (the ones you get in production) only work with async functions so when you have a function that isn't async and just uses promises the chain won't stitch. You can read more on the implementation in the design document the fix fortunately is pretty simple:

// the function has to be async
async function a() {
    // isolate areas that have to use raw promises 
    await new Promise((resolve, reject)=>{
        setTimeout(()=>resolve(), 2000);
    });
    // throw the error from inside the function

    throw new Error('a');
}

Which happily logs:

Error: a
    at a (<anonymous>:6:11)
    at async b (<anonymous>:10:5)
    at async c (<anonymous>:14:5)
    at async test (<anonymous>:23:5)

I could be wrong but I believe its because you create an anonymous function within setTimeout, which would then be thrown for the error.

Maybe not the cleanest, but for every Error I put in a logPrefix, and do something like the below. Just means you can easily debug an error.

const logPrefix = '[my-function-name]'
throw new Error(`${logPrefix} - The error maybe with ${error} injected`)

If my function is within a class or something I might do the below

const logPrefix = '[className.methodName]'

本文标签: