Home > Back-end >  Javascript - Can I safely call an asynchronous function at the end of a synchronous function?
Javascript - Can I safely call an asynchronous function at the end of a synchronous function?

Time:12-25

I can't seem to find a straight forward answer to this one, as almost every resource inverts my question to "Can I call synchronous from within Asynchronous". I'm also asking out of curiosity and with the intention of understanding the relationship between sync and async.

Below is a very basic example of what I was thinking, but I've previously worked with some asynchronous and synchronous elements poorly in the past and want to follow a best practice.

These are all functions I know can safely run first, as most of them are html setups based on a few system details such as date and time.


// Fires from body's onl oad
function startup(){
   // Begin startup and setup
   makeDivs();
   getDate();
   setUpInputHandlers();
   
   
   // Begin API and Async functions
   startupAsync();
}

async function startupAsync(){
   await callApi();
   await doDataWork();
   // more async functions throughout.
}

I'm not looking to do anything synchronous with the async data, but I want a few processes to run before I jump onto my API calls and working with API data. Would something akin to above be a safe way to do this? I know it would be easier to make both startups async.

CodePudding user response:

1.If a function is declared with the async keyword, we can call it with the await.

const getPromise = async (s) => {  
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(s), 500);
    });
}
(async() => {
    try {
        const result = await getPromise("a");   
        console.log('async/await -> ', result);
    } catch (err) {
        console.log(err);
    }
})();

2.But if we declare getPromise without the async keyword, we can still call it with the await keyword. The reason being is getpromise() returns a Promise object. If a function returns a Promise, we can call it with await.

const getPromise = (s) => {  
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(s), 500);
    });
}
(async() => {
    try {
        const result = await getPromise("a");   
        console.log('async/await -> ', result);
    } catch (err) {
        console.log(err);
    }
})();

3.What about calling using the then clause? Of course, before async/await, back when we only had Promise, we declare a function without the async keyword and we call it with the then clause.

   const getPromise = (s) => {  
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(s), 500);
    });
}
(() => {
    getPromise("b")
    .then(result => {
        console.log('then -> ', result);
    })
    .catch(err => {
        console.log(err);
    });
})();

4.So can we declare getPromise() with the async keyword and call it with the then clause? Yes, that works too.

const getPromise = async (s) => {  
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(s), 500);
    });
}
(() => {
    getPromise("b")
    .then(result => {
        console.log('then -> ', result);
    })
    .catch(err => {
        console.log(err);
    });
})();

5.What's not to do is the following case. The outer function which is the caller function is declared without the async keyword. This will cause a run-time error.

const getPromise = async (s) => {    
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(s), 500);
    });
}

//
(() => { //no async keyword here
  try {
    const result = await getPromise("a");   
    console.log('async/await -> ', result);
  } catch (err) {
    console.log(err);
  }
})();

6.but the following is OK:

const getPromise = async (s) => {    
   return new Promise((resolve, reject) => {
     setTimeout(() => resolve(s), 500);
   });
}
(async() => {
    getPromise("b")
    .then(result => {
        console.log('then -> ', result);
    })
    .catch(err => {
    console.log(err);
    });
})();

7.we call getPromise() without the await keyword.In this case, result has not yet been unwrapped, so it's still only a Promise object.

const getPromise = async (s) => {    
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(s), 500);
  });
}

(async() => {
    try {
        const result = getPromise("a"); //no await, result has not been unwrapped   
        console.log('async/await -> ', result);
    } catch (err) {
        console.log(err);
    }
})();

CodePudding user response:

If you want startup() to execute the async functions callApi() and doDataWork() before doing something else, then startup should be an async function too.

async function startup(){
   makeDivs();
   getDate();
   setUpInputHandlers();
   await callApi();
   await doDataWork();
}

await startup()
// then do something afer the async functions finish

If you want to do something else while the async functions run, then startup does not need to be an async function.

function startup(){
   makeDivs();
   getDate();
   setUpInputHandlers();
   (async function(){
     await callApi();
     await doDataWork();
   })();
}

startup()
// do something while async operations run
  • Related