Skip to content

Instantly share code, notes, and snippets.

@FlandreDaisuki
Forked from mmis1000/AbortablePromise.ts
Created March 18, 2020 04:50
Show Gist options
  • Save FlandreDaisuki/b9dd6050bc2fc36434765d5e0ec60736 to your computer and use it in GitHub Desktop.
Save FlandreDaisuki/b9dd6050bc2fc36434765d5e0ec60736 to your computer and use it in GitHub Desktop.
Abortable promise
import AbortController from "abort-controller"
import { AbortSignal } from "abort-controller"
import { AbortablePromise } from "."
var controller = new AbortController()
function sleep (signal: AbortSignal, time: number) {
return AbortablePromise(signal, function (resolve, reject, handleCancel) {
var id = setTimeout(resolve, time)
handleCancel(() => {
clearTimeout(id)
throw new Error('aborted timeout')
})
})
}
async function main (signal: AbortSignal) {
await sleep(signal, 1000)
console.log(1)
await sleep(signal, 1000)
console.log(2)
await sleep(signal, 1000)
console.log(3)
await sleep(signal, 1000)
console.log(4)
await sleep(signal, 1000)
console.log(5)
}
main(controller.signal)
.then(function () {
console.log('resolved')
})
.catch(function (err) {
console.error(err)
})
setTimeout(() => {
controller.abort()
}, 2500)
import AbortController from "abort-controller"
import { AbortSignal } from "abort-controller"
class DOMException extends Error {
name = 'DOMException'
}
export function AbortablePromise<T>(
signal: AbortSignal,
callback: (
resolveFn: (arg: T) => void,
rejectFn: (err: any) => void,
installCancel: (cancelCb: () => T) => void
) => void
) {
return new Promise<T>((resolve, reject) => {
if (signal.aborted) {
// ignore it completely
return reject(new DOMException('Already aborted signal'))
}
// throw dom exception by default
let cancelHandler: () => T = function () {
throw new DOMException('Aborted')
}
let fulfilled = false
function onResolve(res: T) {
if (!signal.aborted) {
signal.removeEventListener('abort', onAbort)
resolve(res)
}
}
function onReject(err: any) {
if (!signal.aborted) {
signal.removeEventListener('abort', onAbort)
reject(err)
}
}
function onAbort() {
signal.removeEventListener('abort', onAbort)
Promise.resolve().then(cancelHandler).then(resolve, reject)
}
signal.addEventListener('abort', onAbort)
callback(onResolve, onReject, function handleCancel(handler) {
cancelHandler = handler
})
})
}
{
"name": "abortable-promise",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"abort-controller": "^3.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment