In a promise system, there are two parties involved, an action initiator, and observers:
let done = fetch(url);
let insertDom = () => console.log("element inserted");
let read = () => done.then(insertDom);
in this example, fetch
is the action initiator, read
is an observer.
I think what we really want from cancelable promises, is the ability to do two things:
- Abort the action.
- Let observers signal that they are no longer interested in the result of the action.
There seems to be some interests in exposing a cancel
method in the promise object, where a observer could signal the action initiator that it should abort the action. This is wrong. ES2015 promises are currently one-way communication APIs. They are simple and easy to be reasoned about, and should be kept that way.
To achieve the first goal, I think the action initiator should have a separate API to abort the action, and when that happens, the returned promise should be rejected with a special error object. This means only when you have access to the action initiator, will you be able to abort the action.
For the second goal, promise objects should expose an API to undo the registering of callbacks done by the then
method, much like what removeEventListener
does to undo addEventListener
in DOM. This means when an observer deregisters before the promise is resolved or rejected, its child promises are going to be in the pending state forever, unless it registers again.
Here are some code examples to illustrate the two points:
let query = queryDB(sql);
query.done // the promise object
query.abort() // abort
let query = queryDB(sql);
let updateView = () => console.log("view updated");
let log = () => console.log("log view updated");
query.done.then(updateView).then(log); // register
query.done.ignore(updateView); // disregister, log will not be called
setTimeout(() => {
query.done.then(updateView); // register again, log will be called.
}, timeEnoughForQueryToFinish);
The API names are debatable.