A final proposal for await syntax

I have an experience report to share.

Yesterday, at work, I wrote some async/await code. I had been struggling to write the code without it, and then it fell into place quite easily with it, so I gave a small cheer. My nearest co-worker asked if I finally got things to work, and wanted to see what the code looked like. I’m not sure what his level of Rust proficiency is (It’s a new job!), though he at least knows some stuff. The project he works on is mostly TypeScript, and uses async/await there. I haven’t participated much in this thread, but prefix await is my preference.

We proceeded to go through about two years of the debate in about five minutes. Here’s the relevant part of the code:

future
    .await
    .expect("promise didn't resolve")
    .as_string()
    .expect("JsValue wasn't a string")

There was of course some more, but this was the most relevant bit. Here’s a from-memory re-enactment of our conversation. Any mistakes are due to my memory :slight_smile:

Him: Wait, is await a… field?

Me: No, it’s a keyword, just postfix.

Him: That seems a bit odd.

Me: Yeah, but let me show you why. (I opened up the playpen) imagine we used the JS syntax:

let value = await future;

Okay so, this is easy. But what about when the future can error? You’d need

let value = await future;
let value = (await future)?;

Him: Oh, because of the precedence of ?? Why not change the precedence of ??

Me: Well, that is an option, but remember, this conversation started off with “oh that looks like a weird special case.” This would also be a weird special case.

Him: That’s fair.

Me: Also, let’s look at the code that motivated this conversation, and what it would look like with both syntaxes:

future
    .await
    .expect("promise didn't resolve")
    .as_string()
    .expect("JsValue wasn't a string")

(await future)
    .expect("promise didn't resolve")
    .as_string()
    .expect("JsValue wasn't a string")

Him: Ah yeah, that does look worse, and also, it gets exponentially worse if you need to chain.

Me: Yep:

let value = future
    .await
    .foo()
    .await
    .bar()

let value = (await (await future).foo()).bar()

Him: Exactly. We run into this in our TypeScript codebase a lot, and it is really unpleasant.

Okay, you’ve sold me. It’s a little weird at first, but I do think it’s better. And besides, you just know that tomorrow, VS: Code will highlight .await in like, neon blinking red or whatever, and it won’t even look like field access.

(He’s got a good sense of humor.)


Anyway, this is obviously just one conversation, and who knows how said conversation would have gone without the other person being me; that is, without someone who can explain the context.

As a side note, at the start of this post, I mentioned that I’m personally more pro-prefix syntax. I still think ultimately that’s true, but at the same time, I’ve made my peace with the postfix syntax. More than anything, I just want this feature to finally ship. .await is still reasonable, even if it’s not my preference.

40 Likes