Re: [whatwg/dom] Expose an `aborted` promise on AbortSignal? (#946)

Our race currently looks like this:

```js
export function race(signal, promise) {
  return Promise.race([ toPromise(signal), promise ]);
}

// The `toPromise` part is used internally but hasn’t needed to be exposed as part of the
// public API of our abort-utils module to date:

let promises = new WeakMap;

function toPromise(signal) {
  if (!promises.has(signal)) {
    promises.set(signal, new Promise((resolve, reject) => {
      let propagate = () => reject(new DOMException('Aborted', 'AbortError'));

      if (signal.aborted) {
        propagate();
      } else {
        signal.addEventListener('abort', propagate);
      }
    }));
  }

  return promises.get(signal);
}
```

It’s not on the prototype for us since it wasn’t polyfilling any (current!) proposed feature. Other than that, the differences seem to be:

1. Your example has `if (this.aborted) throw new DOMException('', 'AbortError');` where ours would be `return Promise.reject(new DOMException(...)` on the first line. In other words, our `race` always returns a promise even if the promise is rejected right away. I think that’s the behavior you’d want (and AFAIK is the only behavior Web IDL would permit).
2. Ours isn’t removing the 'abort' listener after resolution. This seemed harmless in practice as the signals aren’t outliving the operations they’re involved in and a Promise can’t settle twice, but we should be doing it anyway to be safe. Certainly a formalized version of it would want to.

(The same-value returning stuff for `toPromise` is not critical to any of this; it can probably just be ignored.)

> There'd need to be some education around usage of all of these patterns

For sure. I suspect there’s no way around this stuff being a little tricky to grasp, but one of the reasons I came to favor `race` as the “building block” was that it leads to a pretty strong rule of thumb: “when implementing an async operation which is meant to be abortable, everywhere you’d have written `await x` becomes `await signal.race(x)`”. This is what I meant by “decorate await” — we can’t do it with syntax, but we make it feel ... close.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/946#issuecomment-845924476

Received on Friday, 21 May 2021 12:45:01 UTC