Search code examples
asynchronousasync-awaitpromise

await vs then - accessing returned values


Trying to get my head around the subtle (sic) differences between await vs then. I've read most of the posts here, so I get that async functions return a promise.

Using await (with an async function) returns a var that can be used downstream, but using .then (with an async function) does not (at least for me) likewise return a var that can be accessed outside the then clause), since it is processed asynchronously and downstream references are processed synchronously - outside the .then clause, the var (in my example) is undefined.

I understand why my example is behaving the way it does, but my question is - is there a way to use .then with an async function, such that the result can be accessed downstream of the function execution?

let x, y, z;

async function foo ( num ) {
    return Promise.resolve ( num + 10 );
}

async function bar (num) {
    return num + 20;
}

async function baz (num) {
    return Promise.resolve ( num + 30 );
}

async function main (){
    x = await foo(10);
    console.log('foo returned (after await): '+ x); // no hay problema!

    y = await bar (10);
    console.log('bar returned (after await): '+ y); // no hay problema!

    baz (10)
        .then ( (result) =>{
            z = result;
        });
    console.log('baz returned: '+ z); // undefined...executes before .then completes...
}

main(); 

Update

I guess there were some questions about my objective in using x and y outside a set of chained then clauses. Here is a (hopefully more) real-world example of what I'm trying to do:

In the code below, schemaValidation can be used in any of the routes within an express app (said routes are initialized in initAppRouter):

// main
    const schemaDB = await initAppDBSchema ();
    const schemaValidation = await initAppDataValidationSchema();
    const Author = mongoose.model ( 'Author', schemaDB );
    let author: any;
    let authors: any;
    await initAppDB ();
    await initAppRouter ();

    async function initAppDataValidationSchema () {
        return joi.object ( {
            authorName: joi.string ()
                .min ( 3 )
                .max ( 30 )
                .required (),
etc...
        } );
    }  ...

Solution

  • is there a way to use .then with an async function, such that the result can be accessed downstream of the function execution?

    No. There's no reliable way to do that.

    Moreover, you shouldn't need to do that in the first place. Whatever you want to do with the data after the promise chain can be done inside the callback function, once the data is available.

    Using await (with an async function) returns a var that can be used downstream

    Right but that's only possible because of how async-await is transformed in the promise chain. That "downstream" code is actually wrapped in a callback function of then() method.