New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define async algorithms (or "spec promises"???) #181

Open
domenic opened this Issue Dec 12, 2017 · 3 comments

Comments

3 participants
@domenic
Member

domenic commented Dec 12, 2017

https://html.spec.whatwg.org/#fetching-scripts makes use of these extensively, and seems like a reasonable model. However, there are several potential improvements we should discuss:

  • In a recent Chromium code review, I realized that using "asynchronously" is ambiguous. In particular, is it event-loop-async, or do I just mean "can also continue in a future event loop turn"? In general event loop integration is not spelled out. But in practice this leads to an observable difference. I think in most cases I want to allow sync execution of the algorithm, e.g. early-error cases shouldn't need to yield to the event loop before continuing. This should be clarified, probably by defining "asynchronous algorithm" or similar in Infra and then linking to it.

  • Should we have separate error and success channels? #fetching-scripts uses "null"; maybe it should use "failure" instead. I guess that makes more sense than separate channels, since it matches how we do most sync algorithms? Or should there be something more analogous to thrown exceptions?

  • This model is very "callback-ish". Should we try to do something more promise-ish or await-ish? I'm not sure what that would mean; #fetching-scripts already feels fairly await-ish, e.g. we don't indent the steps after getting the result. But it's worth thinking about.

For those last two points, it basically boils down to looking at #fetching-scripts with fresh eyes and letting me know how you would do them differently.

@jakearchibald

This comment has been minimized.

Contributor

jakearchibald commented Dec 12, 2017

Summarising from IRC:

In the "fetching scripts" case, I'd do something like:

  1. Run the following steps in parallel:
    1. Set the script's script to the result of fetch a module script graph.

…And rewrite "fetch a module script graph" to return synchronously. To allow "fetch a module script graph" to perform parallel fetches I'd do something like:

  1. Let urlsToFetch be the list of urls to fetch.
  2. Let abandoned be false.
  3. Let complete be 0.
  4. For each url in urlsToFetch, run the following steps in parallel:
    1. Let response be the result of fetching url.
    2. If response is a failure, then set abandoned to be true.
    3. Otherwise, increment complete.
  5. Wait for abandoned to be true, or complete to be equal to urlsToFetch's length.

I guess that could be easier with spec promises:

  1. Let urlsToFetch be the list of urls to fetch.
  2. Let tasks be a new list.
  3. For each url in urlsToFetch:
    1. Let task be the following steps:
      1. Let response be the result of fetching url.
      2. If response is a failure, return failure.
      3. Otherwise, return true.
    2. Run task in parallel.
    3. Append task to tasks.
  4. Wait for every task in tasks to complete, or any task in tasks to fail.
@domenic

This comment has been minimized.

Member

domenic commented Dec 12, 2017

@jakearchibald's way is better I think; we should try to move fetching-scripts toward that. The magic is in "wait", which ensures that the algorithm can be sync. I'll give it a try ... sometime ... and report back.

At this point it seems more likely this will feed into HTML's event loop stuff than into Infra.

@ricea

This comment has been minimized.

ricea commented Jun 28, 2018

Something that worries me is that to permit the natural expression of the streams API in JavaScript, "spec promises" need to use microtasks. To make matters worse, for efficiency purposes we need to be able to say something like

  1. Return the result of transforming the result of task to a promise.

and have it work "in-place" without introducing an extra layer of microtask execution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment