Skip to content
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

New principle: A Promise represents completion or a value, not a callback (#342) #496

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
47 changes: 47 additions & 0 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1877,6 +1877,53 @@ If the bytes in the buffer have a natural intepretation
as one of the other TypedArray types, provide that instead.
For example, if the bytes represent Float32 values, use a {{Float32Array}}.

<h3 id="allow-microtask-switches">A Promise represents a value, not a callback</h3>
jan-ivar marked this conversation as resolved.
Show resolved Hide resolved

Avoid requiring that something needs to happen synchronously within
a promise resolution or rejection callback.

Authors tend to expect that any `async` function can be wrapped
in another that appends synchronous code at the end.
This might be to examine a resolved value or rejection using try/catch.
But using `await` or similar wrappers queue a microtask:
<div class="example">
```js
async function fooWrapper() {
const foo = await platform.foo();
console.log("success");
return foo;
}

(async () => {
const foo = await fooWrapper();
foo.bar(); // on the same task, but not the same microtask that logged "success"
})();
```
</div>

In general, the settled result from an asynchronous function
should be usable at any time.

However, there could be cases where APIs might need to restrict
when a result can be acted on.

In the above example, perhaps the `platform.foo()` function
establishes state that has real-time dependencies such that calling
`bar()` is not viable at any future time.

Never limit the viability of acting on a settled result to a microtask,
as this prevents most forms of code composition.

If possible, set a short timeout interval. Failing that, viability can
be limited to the same task, but not a single microtask.

<div class="note">
jan-ivar marked this conversation as resolved.
Show resolved Hide resolved
One case where this came up was the [captureController.setFocusBehavior()](https://w3c.github.io/mediacapture-screen-share/#dom-capturecontroller-setfocusbehavior)
method, where timing concerns were instead solved by adding a timeout on top of
the requirement of it being called on the same task that resolves the
`getDisplayMedia()` promise.
jan-ivar marked this conversation as resolved.
Show resolved Hide resolved
</div>

<h2 id="event-design">Event Design</h2>

<h3 id="one-time-events">Use promises for one time events</h3>
Expand Down