Cancel promise pattern

All you need to cancel.

by jib1

HTML

<button id="button">Cancel!</button>
<div id="div"></div>

JavaScript

var console = {log: msg => div.innerHTML += msg + "<br>"};

function CancelError() {
  return Object.assign(new Error("The operation was canceled."), {name: "CancelError"});
}

let wait = (ms, cancel = new Promise()) => {
  let id, both = x => [x, x];
  cancel = cancel.then(...both(() => Promise.reject(new CancelError())));
  cancel.catch(() => clearTimeout(id));
  return Promise.race([new Promise(r => id = setTimeout(r, ms)), cancel]);
};

let cancel = new Promise(cancel => button.onclick = cancel);

Promise.resolve()
.then(() => console.log("Wait 3 seconds..."))
.then(() => wait(3000, cancel))
.then(() => console.log("Then wait 2 more seconds..."))
.then(() => wait(2000, cancel))
.then(() => console.log("Then wait 1 more second..."))
.then(() => wait(1000, cancel))
.then(() => console.log("Done."))
.catch(e => e.name == "CancelError" ? console.log("User canceled") : Promise.reject(e))
.catch(e => console.log(e));