-1

I have an async function

async function f1 (){
  some db operation
  return result
}

What is the difference between the two code

await f1()
.then((result)=> something1. Can I use result here?)

vs

f1()
.then((result)=>something2. Can I use result here?)
VLAZ
  • 26,331
  • 9
  • 49
  • 67
Manu Chadha
  • 15,555
  • 19
  • 91
  • 184
  • The short answer would be no. **await** is not necessary when you're already using .then() to handle a Promise. but in your example f1() is not a promise. – Babak Abadkheir Sep 02 '23 at 11:00
  • 3
    @BabakAbadkheir `f1()` is an async function, therefore calling it returns a promise. See [Why is my asynchronous function returning Promise { } instead of a value?](https://stackoverflow.com/q/38884522) | [Async function returning promise, instead of value](https://stackoverflow.com/q/51338277) – VLAZ Sep 02 '23 at 11:05
  • Can I ask if `const result = await f1();` makes `then` superfluous? – GrafiCode Sep 02 '23 at 11:16
  • 1
    @GrafiCode yes and no. Basically anything you can do with `await` you can do with `.then()` and vice versa. With that said, some things might be easier to express as one or the other. Might also depend on what technologies and frameworks you have available. If you're heavily using Ramda, for example, that includes a lot of FP, so `.then()` can feel a lot more natural and you might already have utility functions ready to use with it. – VLAZ Sep 02 '23 at 11:32
  • @VLAZ thank you, I'm thinking about `fetch` -> `then(response.json)` -> `then(data)`, every time I approach that using two `await`s, I feel like I'm doing it wrong. I guess it's lack of experience / knowledge by my side – GrafiCode Sep 02 '23 at 11:42
  • While await is not necessary in your examples the two options *will* yield different results especially if used in succession. If you have two successive calls to `f1()` and don't use `await` they will be queued simultaneously, where as with `await` each would need to finish before the next call would start. – pilchard Sep 02 '23 at 12:41
  • If I understand @pilchard's answer correctly, `then` always get executed. `await` affects what is after and outside the `then` block. Whether that will be blocked or not depends on whether `await` is used or not when calling an `async` function. – Manu Chadha Sep 02 '23 at 15:01

3 Answers3

2

You are asking two questions, one in your title and one in the body of your question.


"Is using await necessary with .then?"

No, but using it will change the flow of your code.

see: What is the order of execution in JavaScript promises? for a detailed explanation.


"What is the difference between the two code?"

Your first example will pause execution until the promise returned by the .then is settled so the following will log:

Result:  42
After f1() call

async function f1() {
  await new Promise(resolve => setTimeout(resolve, 2000));
  return 42;
}

(async () => {
  await f1().then(result => console.log("Result: ", result));

  console.log("After f1() call");
})();

Your second example will make the call and then immediately continue synchronous execution with the .then called asynchronously after it finishes and will log:

After f1() call
Result:  42

async function f1() {
  await new Promise(resolve => setTimeout(resolve, 2000));
  return 42;
}

(async () => {
  f1().then(result => console.log("Result: ", result));

  console.log("After f1() call");
})();
pilchard
  • 12,414
  • 5
  • 11
  • 23
  • If I understand the answer correctly, `then` always get executed even if the upper level function exits. `await` affects the code which comes after and outside the `then` block in the upper level function. Whether that code will be blocked or not depends on whether `await` is used or not when calling an `async` function. – Manu Chadha Sep 02 '23 at 15:02
1

To answer your immediate question: "Is using await necessary with then": no.

The two examples in your question aren't really comparable. Both examples are the same but in the first you've mysteriously added a redundant await keyword.

The question you should ask is "What are the different approaches to using promises?" something that MDN covers well in the documentation "How to use promises".

These updated examples are comparable. The first uses "traditional" thenable syntax. The second uses newer async/await syntax.


f1().then(result => console.log(result));
const result = await f1();
console.log(result);
Andy
  • 61,948
  • 13
  • 68
  • 95
  • The difference being that `result` is available as a top level variable in the second case – pilchard Sep 02 '23 at 12:30
  • That's the difference between the examples in my answer and not the examples in the OP's question, but fair point; I probably could have been clearer. – Andy Sep 02 '23 at 12:32
0

TL:DR

The difference is that the statement following the first code is executed asynchronously, whereas the statement following the second code is executed synchronously.


Precedence of chaining (calling then) and await

The await operator has lower precedence than both the . operator used for "member access" to access methods of a promise object, and function calls to the method once accessed. In fact, member access and function calls have the same priority and will be executed from left to right.

Hence in this code

await f1().then(result=>// code using the result)
// next statement

the await operator is waiting for the last promise in the chain to be fulfilled. You can use result in the fulfillment handler as a matter of course- that's how fulfilling the promise returned by f1() passes its return value to the next handler in the chain. The next statement is executed asynchronously, after the value of result has been determined and processed. More generally if the promise chain contained more than two promises, the next statement would be executed after the last promise in the chain becomes fulfilled.

In the second code,

f1().then(result=>// code using the result)
// next statement

you can still use result in the fulfillment handler - nothing has changed with how promise chains operate. But without the await operator, the statement following the promise chain is executed synchronously, without waiting for any promise in the chain to be settled, including the promise returned by f1().

traktor
  • 17,588
  • 4
  • 32
  • 53