cancelable
This proposal tries replacing cancellation token from cancelable-promise with cancellation chain object, to achieve more automatic cancellation propagation.
TODO
chain
keyword may be able to be confused with normal promise then
chain.
Promise.cancelable(async (chain) => { /* ... */ });
promise[@@cancel]
New CancelableChain
object is passed to promise constructor callback. This object can store other promises and cancel them when its underlying promise gets canceled. Its constructor is exposed to make a standalone chain instead of Promise dependant one.
interface CancelableChain {
constructor(): CancelableChain;
<T>(cancelable: CancelablePromise<T>): Promise<T>;
(cancelable: Cancelable): Promise<void>;
cancel(): void;
canceled: boolean;
tillCanceled: Promise<void>;
throwIfCanceled: void;
[[chainedList]]: Cancelable[];
}
interface Cancelable {
[@@cancel](): void;
}
interface Promise<T> extends Cancelable {}
Use
function inner() {
return Promise.cancelable(async (chain) => {
await a();
chain.throwIfCanceled();
await b();
});
}
function outer() {
return Promise.cancelable(async (chain) => {
await chain(inner());
});
}
function inner() {
return Promise.cancelable(async (chain) => {
await a();
if (!chain.canceled) {
await b();
}
});
}
function inner() {
return Promise.cancelable(async (chain) => {
const state = { foo: false }
chain.tillCanceled.then(() => state.foo = true);
await c(state);
});
}
Syntax sugar
A cancelable function
has a new chain
keyword in its function scope.
cancelable function inner() {
await a();
chain.throwIfCanceled();
await b();
}
cancelable function outer() {
chain inner();
}
cancelable function inner() {
await a();
if (!chain.canceled) {
await b();
}
}
Token style to chain style
chain(promise)
returns input promise so that promise.then can happen after chaining.
let chain = new CancelableChain();
chain(fetch())
.then(() => chain(process()));
chain.cancel();
This example with .then()
works basically same as the following example.
let chain = new CancelableChain();
chain(fetchAndProcess());
chain.cancel();
cancelable function fetchAndProcess() {
chain fetch();
chain process();
}