Last active
September 12, 2019 08:39
-
-
Save bitifet/28f126a11514ceff7b389cec7fe979eb to your computer and use it in GitHub Desktop.
Promise Cancellator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Promise cancellation utility | |
// Inspired on this @getify tweet: | |
// https://twitter.com/getify/status/1171820071582339072 | |
// (Deferrable version) | |
// ----- IMPLEMENTATION: ----- | |
function cancellator() { | |
let cancelTimowut = null; | |
let cancelMessage = "Cancelled"; | |
const stoppers = []; | |
function stop({t0, reject}){ | |
if (! cancelTimeout) { | |
reject(cancelMessage); | |
} else { | |
const now = Date.now(); | |
const t = t0+cancelTimeout; | |
const remain = t - now; | |
if (remain <= 0) { | |
reject(cancelMessage); | |
} else { | |
setTimeout(()=>reject(cancelMessage), remain); | |
}; | |
}; | |
}; | |
const API = { | |
control: p=>new Promise(function(resolve, reject) { | |
const stopper = { | |
t0: Date.now(), | |
reject, | |
}; | |
if (cancelTimeout !== null) { | |
stop(stopper); | |
} else { | |
stoppers.push(stopper); | |
}; | |
p.then(resolve, reject); | |
return API; | |
}), | |
abort(msg, timeout = 0) { | |
if (msg) cancelMessage = msg; | |
cancelTimeout = timeout; | |
stoppers.map(stop); | |
return API; | |
}, | |
}; | |
return API; | |
}; | |
// --------------------------- | |
// --------- MOCKS: ---------- | |
const sleep = t=>new Promise((rs)=>setTimeout(rs, t*1000)); | |
const fetch = (url="??")=>sleep(Math.random()*5) // Fake fetch | |
.then( | |
()=>Math.round(Math.random()) | |
? Promise.resolve('Ok: '+url) | |
: Promise.reject('Error: '+url) | |
) | |
; | |
// --------------------------- | |
// ------ ACTUAL CODE: ------- | |
async function send(data, C=x=>x) { | |
try { | |
const res = await C(fetch(data)); | |
console.log(res); | |
} catch (err) { | |
console.error("TROWN: " + err); | |
}; | |
}; | |
const onSend = (function(prevSend){ | |
let c = 0; // Count button pushes | |
return function do_onSend(evt) { | |
prevSend.finally(async function(){ | |
await send(++c | |
, cancellator().abort("CANCELLED!!: " +c, 2000).control | |
); | |
}); | |
}; | |
})(Promise.resolve()); | |
// --------------------------- | |
// ------- SIMULATION: ------- | |
async function randomPush() { | |
await sleep(Math.random()*3); | |
onSend(); | |
return randomPush(); | |
}; | |
randomPush(); | |
// --------------------------- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Promise cancellation utility | |
// Inspired on this @getify tweet: | |
// https://twitter.com/getify/status/1171820071582339072 | |
function cancellator() { | |
const stoppers = []; | |
return { | |
control: p=>new Promise(function(resolve, reject) { | |
stoppers.push(reject); | |
p.then(resolve, reject); | |
}), | |
abort: (msg)=>stoppers.map(s=>s(msg)), | |
}; | |
}; | |
// ------ EXAMPLE: ------- // | |
const sleep = t=>new Promise((r)=>setTimeout(r, t*1000)); | |
async function doSomething(msg, C=x=>x) { | |
for (let i=1; i<=3; i++) { | |
await C(sleep(1)); | |
console.log(`${msg} ${i}`); | |
}; | |
}; | |
doSomething("Uncancellable").catch(console.error); | |
const c = cancellator(); | |
doSomething("Cancellable", c.control).catch(console.error); | |
sleep(2).then(()=>c.abort("Operation cancelled!!!")); | |
// ----------------------- // | |
// ------- OUTPUT: ------- // | |
// Uncancellable 1 // | |
// Cancellable 1 // | |
// Operation cancelled!!! // | |
// Uncancellable 2 // | |
// Uncancellable 3 // | |
// ----------------------- // |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment