Skip to content

Instantly share code, notes, and snippets.

@aztack
Created January 22, 2021 03:53
Show Gist options
  • Save aztack/82c3ff256b1cc56b3bc79ab4384051d5 to your computer and use it in GitHub Desktop.
Save aztack/82c3ff256b1cc56b3bc79ab4384051d5 to your computer and use it in GitHub Desktop.
Execute cancelable promises one by one
var u = 2000
function cancableDelay(delay, callback, before) {
return () => {
let timer;
const promise = new Promise((rs, rj) => {
let ret = true
if (typeof before === 'function') {
ret = before(rs, rj) !== false;
}
if (ret) {
timer = setTimeout(() => callback(rs, rj), delay);
console.log(`create timer=${timer}`)
}
});
promise.cancel = () => {
console.log(`Canceling ${timer}`)
clearTimeout(timer);
}
return promise;
}
}
function playAudio(name) {
return cancableDelay(u, (rs) => {
console.log(`${name} ended`);
rs(`${name} ended`);
})
}
function showGuide() {
return cancableDelay(u, (rs) => {
console.log(`guide showed`);
rs(`guide showed`);
})
}
function delay(sec) {
return cancableDelay(sec * 1000, (rs) => {
console.log(`${sec}s elapsed`)
rs(`${sec}s elapsed`)
}, () => {
console.log(`${sec}s countdown`);
return true;
})
}
let cancel = false;
var promises = [
playAudio('a'),delay(2),
playAudio('b'),delay(2),
showGuide()
];
asyncSequence(promises).then(() => console.log('Done!'))
document.addEventListener('click', () => {
cancel = true;
})
function asyncSequence (array) {
let prevPromise;
return (function chain (array, index) {
if (cancel) console.log('canceling')
if (index === array.length || cancel) {
if (cancel && prevPromise && prevPromise.cancel) {
console.log('canceled')
prevPromise.cancel();
}
return Promise.resolve();
}
let f = array[index];
prevPromise = p = f;
if (typeof f === 'function') prevPromise = p = f();
return p.then(_ => {
return chain(array, index + 1)
});
})(array, 0)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment