await all promises in a code block

Problem: When using ES for batch scripts, code blocks tend to get cluttered by awaits.

For example when looking at code samples for the popular playwright library almost every line is prefixed by an await. IMO that makes the code a bit harder to read:

test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await page.getByRole('link', { name: 'Get started' }).click();
  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();

  // ... to be followed by many more awaits
});

Possible solution (?): I feel like I should be able to write the same with something like this:

test('get started link', sync ({ page }) => {
  page.goto('https://playwright.dev/');
  page.getByRole('link', { name: 'Get started' }).click();
  expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});

The sync keyword would cause every expression inside the code block to be awaited. (The code block itself would still return a Promise that one can await though.)
I understand how this would be ambiguous and thus adverse in web programming, where we seldom want to block the flow of events. But for batch jobs it would be nice, right?.

The await points are important enough to warrant being explicitly annotated. I don't think there's any appetite to make them more implicit.

Ah, sorry, this is more or less a duplicate of this (Looked for it, but couldn't find it yesterday):

However... in that thread, the proposal I accidentally duplicated got shot down early and other alternatives were discussed.

I don't quite agree with the mentioned disadvantages of that proposal though:

Well but async is already doing "magic": It turns every return value into a promise, regardless of the function's contents. And await magically determines, if the passed expression actually is a Promise.

The proposed sync keyword (or await block in the other thread) would do the same but additionally await every expression inside the code block (sequentially in the order of expression evaluation).

Yeah, well "appetite" is something very subjective :smile:
But I agree that in web programming await is always "important enough to being explicitly annotated" :+1:
It's just for batch-style scripts that this would really make things more readably IMO. (For code intended for browsers it might even make sense to prohibit the proposed keyword via eslint.)

Consider node's fs.readFile vs fs.readFileSync for example: I've always found it quirky to have a second method that essentially does the same as the first, only that one returns a Promise and the other actually blocks the execution until the file has been read.
But I understand why they additionally introduced fs.readFileSync - for the same reason I'm proposing sync: To not have thousands of await keywords cluttering batch-style scripts.

We generally avoid adding features to JavaScript which would be harmful if used on the web.

No. Blocking i/o is a fundamentally different kind of thing than non-blocking i/o. It's not about whether you have to write await - it changes the whole semantics of your program.

Whether or not you have to write await is really not that important.

(As a matter of history readFileSync predates the promise version of readFile, but the point still applies.)

I am aware it's not the same. I was just drawing a parallel to show that in certain (non-UI) programming scopes there has always been the developer's need to hide the asynchronicity of a function.

Touché. :grinning_face: But still, they could have deprecated all the *Sync functions as soon as async/await became available, had they thought that the new syntax is sufficient.

I can understand that and that kind of concludes the topic for me. :+1:

(If ES is still being designed primarily for browser/UI applications, then it makes no sense to further discuss it. I just had though since there are so many more applications for it nowadays, that this paradigm may have shifted.)

Thank you very much for taking your time to respond in depth! :folded_hands:

1 Like