dom icon indicating copy to clipboard operation
dom copied to clipboard

Proposal AbortSignal.prototype.filter(compare)

Open mariusGundersen opened this issue 10 months ago • 4 comments

What problem are you trying to solve?

There is now an AbortSignal.any([a, b, c]) that makes it possible to combine multiple signals, but there is currently no way to split a an AbortSignal. I therefore propose the instance method AbortSignal.prototype.filter(compare), which would return a new AbortSignal that only triggers if the reason matches some condition. For example:

function(signal){
  const timeoutSignal = signal.filter(reason => reason instanceof DOMException && reason.name === 'TimeoutError'); // only when the reason is a TimeoutError
}

The above example creates a signal that will only trigger if the reason matches that of AbortSignal.timeout(ms). If the reason doesn't match, then the returned signal will never trigger (since abort signals only ever trigger once).

What solutions exist today?

It is fairly easy to implement this today as a separate function (to not pollute the prototype):

function filterAbortReason(signal, compare) {
    if (signal.aborted && compare(signal.reason)) return AbortSignal.abort(signal.reason);
    const abortController = new AbortController();
    signal.addEventListener('abort', () => {
        if (compare(signal.reason)) {
            abortController.abort(signal.reason);
        }
    });
    return abortController.signal;
}

How would you solve it?

The above function could be placed on the AbortSignal prototype:

AbortSignal.prototype.filter = function(compare) {
    if (this.aborted && compare(this.reason)) return AbortSignal.abort(this.reason);
    const abortController = new AbortController();
    this.addEventListener('abort', () => {
        if (compare(this.reason)) {
            abortController.abort(this.reason);
        }
    });
    return abortController.signal;
}

Anything else?

No response

mariusGundersen avatar Apr 18 '24 08:04 mariusGundersen