Async property accessor: ->

The idea is to access a property of an awaited value to allow deep chaining of async operations.

Right now, to accomplish that kind of chaining you need to write:

const baz = await (await (await fetchFoo()).fetchBar()).fetchBaz();

That can get pretty awkward pretty fast. My idea is a new operator that accomplishes this without all the nested parens:

const baz = await fetchFoo()->fetchBar()->fetchBaz();

Additionally, they can be optionally chained like the other property accessors:

const baz = await fetchFoo()?->fetchBar()?->fetchBaz();

I figured that -> seems appropriate for a new property accessor operator, as it's used by other languages like C++ as a way to access a property.

This operator would only be available in an async scope, since it's essentially a shorthand for await.

2 Likes

See https://github.com/tc39/proposal-wavy-dot

3 Likes

Wonderful! I'm seeing now that it's in stage 1. That syntax would be amazing. Fingers crossed!

1 Like

I would love to see this feature out, my class has almost all of the methods are async, and parentheses+await don't look readable after a few chain steps. bravo!

Arrow is nicer than tilde+dot, arrow is a more common syntax.

Wavy dot is meant as a syntax tool to help with eventual-send. The major difference between what is suggested here and eventual-send is pipelining. In a single agent there is no difference, but in distributed systems (e.g. between Workers, or between a client and server), you want to avoid paying the round trip costs, which here would occur because of the intermediary awaits.

To take the above example, you want to send as soon as possible fetchBaz() to the result of fetchBar() which was itself send to the result of fetchFoo(). You only want to await the result of fetchBaz(). Results are represented by promises, and sending a message to a promise means sending the message to the system that is currently in charge of deciding that promise.

These proposals are a little stale, but Agoric has been using these mechanisms for years. eventual-send has a shim in the endo repository, which uses a E helper in place of the ~. syntax. The developer documentations are lacking / out of date, and I believe there is a strong dependency of the eventual-send package on SES for now. There is a Matrix room where you may be able to get some questions answered.

Btw, the pipeline operator will probably be a good approximation of the benefits of wavy-dot, at least until that kind of distributed patterns emerges more fully.

With await:

const baz = await fetchFoo() |> await %.fetchBar() |> await %.fetchBaz();

With E:

const baz = await (fetchFoo() |> E(%).fetchBar() |> E(%).fetchBaz());

With wavy-dot:

const baz = await fetchFoo()~.fetchBar()~.fetchBaz();

Correct me if I'm wrong, but isn't the default pipelining operation basically just what's requested above (modulo timings) with the hypothetical -> operator?

Correct. Sorry if I wasn't clear, but by default eventual-send falls back awaiting non-delegated promises. In a local only environment there is no difference with with the requested feature here.