Frankie Bagnardi (2015-02-28T05:04:06.000Z)
d at domenic.me (2015-03-06T01:17:14.886Z)
My understanding was that it'd look like this: ```js // presumably standard class CancelReason extends Error {} // Promise.cancelable? third party library? function cancelable(p, onCancel){ // todo: refactor into utility function allowing: return cancelable(resultPromise, () => {xhr.abort()}) var doCancel; var cancelPromise = new Promise((resolve, reject) => { doCancel = reason => { reject(new CancelReason(reason)); return raced; }; }); var raced = Promise.race([p, cancelPromise]) .catch(reason => { if (reason instanceof CancelReason) { onCancel(); } return Promise.reject(reason); }); raced.cancel = doCancel; return raced; } function fetchAsync(url) { var resultPromise = new Promise((resolve, reject) => { xhr.open("GET", url, /*async:*/ true); xhr.onload = event => resolve(xhr.responseText); xhr.onerror = event => reject(xhr.statusText); xhr.send(null); }); return cancelable(resultPromise, () => { xhr.abort() }); } fetchAsync(...).then(...); // as expected fetchAsync(...).cancel('reason').catch(...); // .catch gets the CancelReason, and xhr is aborted fetchAsync(...).then(...).cancel(); // TypeError .cancel is undefined ``` And that cancel wouldn't automatically propagate in any way; but it is a simple callback, so can be passed around as desired.