Is there anything wrong with mixing async/await with .then()?
Asked Answered
H

1

4

Take the below code for example. Is there anything wrong with mixing await with .then in scenarios like this? In my opinion it seems pointless and clunky to declare await for each step like const json = await assetParam.json() etc.. when all we really care about is the final response (in this example at least). But someone told me that mixing await with .then can lead to some hard to diagnose bugs and I'm struggling to understand them.

Any information/resources would be greatly appreciated.

async function getParams(assetId) {
  const reqUrl = `https://somelink/${assetId}`
  const assetParam = await fetch(reqUrl)
    .then((res) => res.json())
    .then((json) => json.asset.params)
  return assetParam
}
Hylophagous answered 27/9, 2021 at 13:50 Comment(6)
The whole point of async functions and await is to get around having to build .then() callback chains.Skell
async/await and .then are totally interoperable. IMO it's better to stick to one or the other, at least on a per-module basis, though. And note that in your case assetParam isn't needed, you could just return the chain directly (at which point you don't await anything and don't actually need to make getParams async).Guidon
Voted to reopen. Primarily opinion based seems like a bad close reason because mixing async/await and promises like this is pretty widely accepted as a bad idea, and not a highly debatable/subjective discussion.Banc
const getParams = async url => (await ((await fetch(url)).json())).asset.paramsCarib
Thank you @jonrsharpe, your suggestion to just return the whole chain really helped me out of a similar problem I had.Beckiebeckley
Related canonical: using async await and .then togetherPhotographer
B
5

Either is fine, but mixing them is just weird. You can rewrite your code snippet in the following 2 ways:

function getParams(assetId) {
  const reqUrl = `https://somelink/${assetId}`
  return fetch(reqUrl)
    .then(res => res.json())
    .then(json => json.asset.params)
}

Or:

async function getParams(assetId) {
  const reqUrl = `https://somelink/${assetId}`
  const res = await fetch(reqUrl);
  const json = await res.json();
  return json.asset.params;
}

It's best to just stick to 1 convention in 1 function.

The snippet you shared is very simple, and I wouldn't strongly prefer either approach. Once your asynchronous code gets more complex with branching/loops async/await really will start to make a difference.

Banc answered 27/9, 2021 at 13:55 Comment(4)
How is your opinion an answer?Ephesus
@Ephesus it's not an opinion. The whole point of using await is to avoid using then. There should be a very good reason for mixing them upOneill
@Ephesus anything that is a best practice could be described as 'opinion'. There's few hard truths. Primarily opinion based is mostly for things that are way further on the subjectivity scale.Banc
I see buggy, hard to read code all of the time that mixes the then and await paradigms and almost always indicates the programmer has a weak grasp of promises. This answer is quite objective. You can similarly argue that it's opinion to claim that a big ball of mud is poor architecture, but that's not a serious argument. On the other hand, arguing that monolith is always better than microservices would be opinion-based, or arguing that await should always be used instead of .then.Photographer

© 2022 - 2024 — McMap. All rights reserved.