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
}
ggorlen
  • 44,755
  • 7
  • 76
  • 106
ericsharma
  • 51
  • 1
  • 3
  • 5
    The *whole point* of `async` functions and `await` is to get around having to build `.then()` callback chains. – Pointy Sep 27 '21 at 13:52
  • 4
    `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`). – jonrsharpe Sep 27 '21 at 13:54
  • 3
    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. – Evert Sep 27 '21 at 13:58
  • `const getParams = async url => (await ((await fetch(url)).json())).asset.params` – Lawrence Cherone Sep 27 '21 at 14:04
  • 1
    Thank you @jonrsharpe, your suggestion to just return the whole chain really helped me out of a similar problem I had. – Paul Pritchard Jan 12 '23 at 15:03
  • Related canonical: [using async await and .then together](https://stackoverflow.com/questions/55019621/using-async-await-and-then-together?rq=3) – ggorlen Sep 02 '23 at 19:00

1 Answers1

4

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.

Evert
  • 93,428
  • 18
  • 118
  • 189
  • 1
    How is your opinion an answer? – Andreas Sep 27 '21 at 14:13
  • 2
    @Andreas 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 up – Panagiotis Kanavos Sep 27 '21 at 14:24
  • 2
    @Andreas 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. – Evert Sep 27 '21 at 15:08
  • 1
    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](https://en.wikipedia.org/wiki/Anti-pattern#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`. – ggorlen Mar 19 '23 at 16:37