2

can someone explain to me the differenec between the two line of code. In my atom editor the prettier changes the first to second.

(await fetchSearchResults(state.requestConfig, context))?.facilities ?? [] ) 

and

await fetchSearchResults(state.requestConfig, context)?.facilities ?? [] )
VLAZ
  • 26,331
  • 9
  • 49
  • 67

3 Answers3

2

The two lines are not the same and any automated change between these two is most likely incorrect.

To simplify, the difference is between:

  1. (await foo()).bar
  2. await foo() .bar:

Due to the operator precedence of await the second code (await foo().bar) will:

  1. Execute foo()
  2. Read the property bar from it
  3. await that value

Which can be written as:

const functionResult = foo();
const result = await functionResult.bar;

While the first code uses the grouping operator () to change the order of operations to:

  1. Execute foo()
  2. await that value
  3. Read the property bar from it

Which can be written as:

const functionResult = await foo();
const result = functionResult.bar;

This absolutely makes a difference if the function returns a promise:

function foo() {
  return Promise.resolve({ bar: "hello world" });
}

async function main() {
  console.log( await foo() .bar); // undefined - `foo()` returns a promise and there is no `bar` property
  console.log((await foo()).bar); // "hello world" - since the promise resolves to { bar: "hello world" }
}

main();

It also makes a difference if foo() is synchronous but the bar property is a promise:

function foo() {
  return { bar: Promise.resolve("hello world") };
}

async function main() {
  console.log( await foo() .bar); // "hello world" since the promise resolves to that string
  console.log((await foo()).bar); // Promise (check the browser console)
}

main();

The only time it does not make a difference is if there is no asynchronous code (which means the await probably should not be there):

function foo() {
  return { bar: "hello world" };
}

async function main() {
  console.log( await foo() .bar); // "hello world"
  console.log((await foo()).bar); // "hello world" 
}

main();
VLAZ
  • 26,331
  • 9
  • 49
  • 67
1

Prettier changes the whole thing to follow the rules given in a Prettier config file.
In your specific case, the (await fetchSearchResults(state.requestConfig, context)) is useless, hence why Prettier strips it.

Meanwhile, it may be quite important in a classic async context as explained in the comment below. Maybe the optional chaining is somehow tricking Prettier here, not sure.


The default Vue2 ESlint configuration comes with plugin:vue/essential and eslint:recommended as defaults.
Here is a link where you could get more details as of why.

If it's Prettier only, check the options part of the documenation or a .prettierrc config file in your project (or above).

kissu
  • 40,416
  • 14
  • 65
  • 133
  • 1
    It's not the same, though: `await foo().bar` means that `foo()` executes, then `.bar` is read from it *and that value is awaited*. While `(await foo()).bar` means to first await the result of `foo()` then take the property `bar` from it. If `foo()` returns a promise then `await foo().bar` is wrong, as it reads `bar` from the promise. Compare [`foo()` returns a promise](https://jsbin.com/rutopazuzi/1/edit?js,console) and [`foo().bar` returns a promise](https://jsbin.com/redereweji/edit?js,console) – VLAZ May 12 '22 at 12:51
  • @VLAZ hm, I always thought that the left part was awaited before reading the right part. I don't usually chain things like that, hence why I may be wrong. Still, would ESlint + Prettier strip that if it had a different meaning? I have to say that I trust those tools pretty well and never had any issues so far. – kissu May 12 '22 at 12:56
  • 1
    I've no idea which tool changed this code. But the semantics are absolutely not the same. It *might* be that `fetchSearchResults()` does not return a promise and nothing in the code is asynchronous. Then the brackets would be superfluous. The `await` would technically not be needed then, however, removing it *can* have more impact, as an `await` will still pause an async function and with asynchronicity this can lead to different results if the execution stops or doesn't stop in the middle of `fetchSearchResults()`. Overall, the change is strange. – VLAZ May 12 '22 at 12:59
  • Just double checked and yeah indeed, the meaning is quite different. In case of a promise, you'll need to wrap the async call into some `()` to then access a key from it. Updating my answer. – kissu May 12 '22 at 13:02
0

You don't need those brackets as long as you are not going to use the promise result straight after as in the example below

(await fetchSearchResults(state.requestConfig, context))?.facilities ?? [] )?.someMethod()

but the line is already getting quite long so you are probably best assigning the promise result to a variable.

Piotr Ostrowski
  • 520
  • 5
  • 8