1

I've written a bit of code that looks like this:

async function fetchData() {
    const json = await fetch(ENDPOINT + key.key).then(data => data.json());
    //Do something with the data
}

It's pretty clear and straight forward what I'm doing here.

I'm just wondering if it's normal to combine both the older Promise style, and the new async/await style like this.

If I wasn't to use .then then I'd be something like this:

async function fetchData() {
    const data = await fetch(ENDPOINT + key.key); 
    const json = await data.json(); 
    //do something with the data
}

Unless I'm missing something here? I guess the question is - is the purpose of async/await to stop using promises completely - or what?

  • if it was c# i'd expect the 2nd version but in javascript 'then' seems to be much more popular than the equivilant .ContinueWith – Ewan Sep 15 '18 at 9:16
  • ..although, do you need the second await? – Ewan Sep 15 '18 at 9:17
  • is the purpose of async/await to stop using promises completely? -- No, async functions return promises. See javascript.info/async-await – Robert Harvey Sep 15 '18 at 16:35
1

Even in modern application development promises are very useful and you generally do not want to await everything. Why? Because awaiting something is blocking.

Imagine a scenario, where you would have an application and upon opening a screen you would need to call two unrelated REST endpoints.

function loadMyProfileData(userId) { ... }
function loadOrders(userId) { ... }

Both of those functions would do an HTTP REST request and return a promise. If you had the following function:

async function onScreenLoad(userId) {
    this.profileData = await loadMyProfileData(userId);
    this.orders      = await loadOrders(userId);
}

you would only start loading the orders once your profile data is fetched, even though the orders function clearly does not depend on the result of profile data at all.

In such scenario you would most likely want to be looking for something like this:

async function onScreenLoad(userId) {
    let [profileData, orders] =
        await Promise.all([loadMyProfileData(userId), loadOrders(userId)]);

    this.profileData = profileData;
    this.orders      = orders;
}

That way you load the data at the same time.

async/await is an amazing syntax sugar but is not to be taken for granted and used without knowing it's side effects.

  • Couldn’t you use just let t1 = loadMyProfileData(userId); let t2 = loadOrders(userId); this.profileData = await t1; this.orders = await t2;? This variant seems to be simpler than Promise.all. – Vlad Sep 16 '18 at 5:49
  • @Vlad, yes, you can do that too. I don't believe it's simpler (or more complex either), I believe it's a matter of personal preference. With your approach, while being correct, you're relying that the promises will execute in parallel and there's also the overhead of having to setup them before. I feel like the parallel execution intent is not completely clear from your code. My demonstration, while not perfect, contains this intent of parallel execution (however it's not idea either). The optimal solution would probably be memoizing the promises and awaiting those. – Andy Sep 16 '18 at 7:34
1

Async await is promises under the hood. So, you can get away with async await most of the time when you have a sequence of dependent async steps to perform.

However, there are times when you want to run a set of operations in series or parallel. There you'll definitely need Promise.all or await in a for loop.

Regarding your code:

  1. You need not await on the return statement of an async function, you can simply return the promise directly.
  2. Keeping a promise in a variable is only needed when you want to do something other than await on it.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.