Search code examples
javascriptasynchronouspromisechaining

Understanding what triggers moving to the next .then() of a javascript promise chain


I had a promise chain that looked something like this.

fistAsyncFunction()
    .then(() => {
        secondAsyncFunction()
    })
    .then(() => {
        thirdAsyncFunction()
    })

I noticed that the third async function was starting before the second async function finished, but after changing it to this, it worked how I wanted it to.

fistAsyncFunction()
    .then(() => {
        return secondAsyncFunction()
    })
    .then(() => {
        thirdAsyncFunction()
    })

It seems like even though the second async function didn't return anything, the program waited for it to return undefined before moving onto the next promise. Is this what's actually happening? If not, then what is going on under the hood that prompts javascript to start executing the next promise?


Solution

  • Think about it this way

    fistAsyncFunction()
        .then(() => {
            secondAsyncFunction()
            return undefined
        })
        .then((iAmUndefined) => {
            thirdAsyncFunction()
            return undefined
        })
    

    ^ This is your first example with explicit returns.

    It seems like even though the second async function didn't return anything, the program waited for it to return undefined before moving onto the next promise.

    So you are sort of right on this one. The second async function does not return anything; that is correct. The program, however, does not wait for secondAsyncFunction() to return undefined. Moreover, it does not wait for secondAsyncFunction() at all. Instead, your program is saying

    Okay secondAsyncFunction I will now call you and let you run away; I will not wait for you. Instead I'm just going to return undefined and move on. Hello thirdAsyncFunction!

    You are correct in noticing that your thirdAsyncFunction is started before your secondAsyncFunction returned.

    Next, you made an amendment to your code to achieve your expected behavior

    fistAsyncFunction()
        .then(() => {
            return secondAsyncFunction()
        })
        .then(resultOfSecondAsyncFunction => {
            thirdAsyncFunction()
            return undefined
        })
    

    ^ this is your second example with explicit returns

    Your program is now working the way you want it to because by returning secondAsyncFunction(), you are now instructing your program to wait for the return of that function.

    what is going on under the hood that prompts javascript to start executing the next promise?

    Under the hood, there is a special function resolve that is used in the Promise constructor. The next promise will start executing when the resolve function of the previous promise is called. Of course, both promises must be tied together by a .then.