0

For the code below why does "A" and "B" get printed before the error 'a'

var a = async()=>{
    return new Promise(async (resolve,reject)=>{
        var v = await ab().catch((err)=>{
            console.log("error")
            return reject(err)
        })
        console.log("A")
        console.log("B")
    })
}

function ab(){
    return new Promise((resolve,reject)=>{
        return reject("a")
    })
}

async function e(){
    try{
        await a()
    }catch(e){
        console.log(e)
    }
}
e()

The output for the above code is error A B a

Shouldn't it be "error" followed by 'a'

Why are A and B getting printed?

Nitin Khare
  • 147
  • 2
  • 10
  • 2
    Recommend you read through some of these answers: https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it – Randy Casburn Feb 17 '21 at 18:05
  • @RandyCasburn - Heh, was just going to find my link to that. :-D – T.J. Crowder Feb 17 '21 at 18:06
  • I hope you realize that you should never be coding this way. Wrapping an existing promise in another promise is a promise anti-pattern. – jfriend00 Feb 17 '21 at 18:11

1 Answers1

3

Because there's no reason it shouldn't. The return is in a callback function, so it only returns from that callback function. It does reject the outer promise, but doing that doesn't prevent the remainder of the code in your promise executor (the function you pass new Promise) from continuing.

There are several problems with the code shown, though.

  1. If you already have a promise, you don't need to create a new one. In a, for instance, you have the promise from ab, so there's no reason for new Promise. This is often called the explicit Promise creation antipattern, this question's answers go into detail.

  2. Using await in a promise executor function generally doesn't make much sense and probably means the executor is doing too much. The purpose of a promise executor is to start an asynchronous process, not to wait for one.

  3. Using .catch/.then/.finally inside an async function is generally not best practice; just use await and try/catch.

Your a function should probably be just:

const a = async () => {
    try {
        await ab();
        // Or you might put the `console.log`s here, there are
        // reasons for each, but it doesn't matter given we're
        // rethrowing the error
    } catch (err) {
        console.log("error")
        throw err;
    }
    console.log("A")
    console.log("B")
};

That will reject the promise a returns when ab's promise rejects, using the same rejection reason, and terminate a's logic rather than allowing it to continue; if ab's promise doesn't reject, it will run the two console.log statements.

Live Example:

const a = async () => {
    try {
        await ab();
        // Or you might put the `console.log`s here, there are
        // reasons for each, but it doesn't matter given we're
        // rethrowing the error
    } catch (err) {
        console.log("error")
        throw err;
    }
    console.log("A")
    console.log("B")
};

function ab() {
    return new Promise((resolve, reject) => {
        return reject("a");
    });
}

async function e() {
    try {
        await a();
    } catch (e) {
        console.log(e);
    }
}
e();
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Yes, I do know about the fact that it should have been the way 'a' function is defined here. It's a question I received from someone. it got me thinking that it could be the callback function that the catch has but just couldn't confirm from anyone I know. Thanks for clarifying though. – Nitin Khare Feb 17 '21 at 18:16
  • 1
    @NitinKhare - Good to know the people writing that were doing it weirdly on purpose. (Well, I assume they were. :-D ) In future, I suggest you mention that it was a puzzle you were given, because explaining just the part you ask about then makes sense rather than going into the greater context. Happy coding! – T.J. Crowder Feb 17 '21 at 18:23