cancelable-promise
Advanced tools
Comparing version 3.1.3 to 3.2.0
@@ -0,1 +1,53 @@ | ||
## [3.2.0](https://github.com/alkemics/CancelablePromise/releases/tag/v3.2.0) (2020-10-10) | ||
- feature: execute onCancel or finally callback when promise is canceled | ||
```javascript | ||
import CancelablePromise from 'cancelable-promise'; | ||
const promise = new CancelablePromise((resolve, reject, onCancel) => { | ||
const worker = new Worker('some-script.js'); | ||
onCancel(() => { | ||
worker.terminate(); | ||
}); | ||
worker.onmessage = (event) => resolve(event.data); | ||
worker.onerror = (error) => reject(error); | ||
}); | ||
promise.cancel(); // It will execute the callback passed to onCancel | ||
``` | ||
```javascript | ||
let worker; | ||
const promise = cancelable( | ||
new Promise((resolve, reject) => { | ||
worker = new Worker('some-script.js'); | ||
worker.onmessage = (event) => { | ||
resolve(event.data); // never executed | ||
}; | ||
worker.onerror = (error) => { | ||
reject(error); // never executed | ||
}; | ||
}) | ||
) | ||
.then(() => { | ||
console.log('never logged'); | ||
}) | ||
.finally( | ||
() => { | ||
console.log('executed'); | ||
if (worker) { | ||
worker.terminate(); | ||
worker = null; | ||
} | ||
}, | ||
// runWhenCanceled boolean | ||
true | ||
); | ||
promise.cancel(); | ||
``` | ||
## [3.1.3](https://github.com/alkemics/CancelablePromise/releases/tag/v3.1.3) (2020-08-31) | ||
@@ -2,0 +54,0 @@ |
@@ -1,4 +0,5 @@ | ||
type PromiseExecutor<T> = ( | ||
type CancelablePromiseExecutor<T> = ( | ||
resolve: (value?: T | PromiseLike<T>) => void, | ||
reject: (reason?: any) => void | ||
reject: (reason?: any) => void, | ||
onCancel: (cancelHandler: () => void) => void | ||
) => void; | ||
@@ -57,3 +58,4 @@ | ||
finally( | ||
onfinally?: (() => void) | undefined | null | ||
onfinally?: (() => void) | undefined | null, | ||
runWhenCanceled?: boolean | ||
): CancelablePromiseType<T>; | ||
@@ -73,4 +75,4 @@ | ||
*/ | ||
new <T1>(executorOrPromise: PromiseExecutor<T1>): CancelablePromiseType<T1>; | ||
<T1>(executorOrPromise: PromiseExecutor<T1>): CancelablePromiseType<T1>; | ||
new <T1>(executor: CancelablePromiseExecutor<T1>): CancelablePromiseType<T1>; | ||
<T1>(executor: CancelablePromiseExecutor<T1>): CancelablePromiseType<T1>; | ||
@@ -77,0 +79,0 @@ /** |
@@ -35,37 +35,72 @@ (function (global, factory) { | ||
function thenFunc(options, onSuccess, onError) { | ||
return cancelable(this.then(createCallback(onSuccess, options), createCallback(onError, options)), options); | ||
} | ||
function makeCancelable(promise, options) { | ||
var methods = { | ||
then: function then(onSuccess, onError) { | ||
return makeCancelable(promise.then(createCallback(onSuccess, options), createCallback(onError, options)), options); | ||
}, | ||
catch: function _catch(onError) { | ||
return makeCancelable(promise.catch(createCallback(onError, options)), options); | ||
}, | ||
finally: function _finally(onFinally, runWhenCanceled) { | ||
if (runWhenCanceled) { | ||
if (!options.finallyList) { | ||
options.finallyList = []; | ||
} | ||
function catchFunc(options, onError) { | ||
return cancelable(this.catch(createCallback(onError, options)), options); | ||
} | ||
options.finallyList.push(onFinally); | ||
} | ||
function finallyFunc(options, onFinally) { | ||
return cancelable(this.finally(onFinally), options); | ||
} | ||
return makeCancelable(promise.finally(function () { | ||
if (runWhenCanceled) { | ||
options.finallyList = options.finallyList.filter(function (callback) { | ||
return callback !== onFinally; | ||
}); | ||
} | ||
function cancelFunc(options) { | ||
options.isCanceled = true; | ||
} | ||
return onFinally(); | ||
}), options); | ||
}, | ||
cancel: function cancel() { | ||
options.isCanceled = true; | ||
function isCanceled(options) { | ||
return options.isCanceled; | ||
} | ||
for (var _i = 0, _arr = [options.onCancelList, options.finallyList]; _i < _arr.length; _i++) { | ||
var callbacks = _arr[_i]; | ||
function cancelable(promise) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { | ||
isCanceled: false | ||
if (callbacks) { | ||
while (callbacks.length) { | ||
var onCancel = callbacks.shift(); | ||
if (typeof onCancel === 'function') { | ||
onCancel(); | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
isCanceled: function isCanceled() { | ||
return options.isCanceled === true; | ||
} | ||
}; | ||
return { | ||
then: thenFunc.bind(promise, options), | ||
catch: catchFunc.bind(promise, options), | ||
finally: finallyFunc.bind(promise, options), | ||
cancel: cancelFunc.bind(promise, options), | ||
isCanceled: isCanceled.bind(promise, options) | ||
then: methods.then.bind(undefined), | ||
catch: methods.catch.bind(undefined), | ||
finally: methods.finally.bind(undefined), | ||
cancel: methods.cancel.bind(undefined), | ||
isCanceled: methods.isCanceled.bind(undefined) | ||
}; | ||
} | ||
function cancelable(promise) { | ||
return makeCancelable(promise, {}); | ||
} | ||
function CancelablePromise(executor) { | ||
return cancelable(new Promise(executor)); | ||
var onCancelList = []; | ||
return makeCancelable(new Promise(function (resolve, reject) { | ||
return executor(resolve, reject, function (onCancel) { | ||
onCancelList.push(onCancel); | ||
}); | ||
}), { | ||
onCancelList: onCancelList | ||
}); | ||
} | ||
@@ -72,0 +107,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(e,n){var t;"function"==typeof define&&define.amd?define(["exports"],n):"undefined"!=typeof exports?n(exports):(n(t={}),e.CancelablePromise=t)}("undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:this,function(e){"use strict";function i(n,t){if(n)return function(e){return t.isCanceled?e:n(e)}}function r(e){var n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{isCanceled:!1};return{then:function(e,n,t){return r(this.then(i(n,e),i(t,e)),e)}.bind(e,n),catch:function(e,n){return r(this.catch(i(n,e)),e)}.bind(e,n),finally:function(e,n){return r(this.finally(n),e)}.bind(e,n),cancel:function(e){e.isCanceled=!0}.bind(e,n),isCanceled:function(e){return e.isCanceled}.bind(e,n)}}function n(e){return r(new Promise(e))}Object.defineProperty(e,"__esModule",{value:!0}),e.cancelable=r,e.CancelablePromise=n,e.default=void 0,n.all=function(e){return r(Promise.all(e))},n.allSettled=function(e){return r(Promise.allSettled(e))},n.race=function(e){return r(Promise.race(e))},n.resolve=function(e){return r(Promise.resolve(e))},n.reject=function(e){return r(Promise.reject(e))},e.default=n}); | ||
!function(n,e){var i;"function"==typeof define&&define.amd?define(["exports"],e):"undefined"!=typeof exports?e(exports):(e(i={}),n.CancelablePromise=i)}("undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:this,function(n){"use strict";function t(e,i){if(e)return function(n){return i.isCanceled?n:e(n)}}function l(i,r){var n={then:function(n,e){return l(i.then(t(n,r),t(e,r)),r)},catch:function(n){return l(i.catch(t(n,r)),r)},finally:function(e,n){return n&&(r.finallyList||(r.finallyList=[]),r.finallyList.push(e)),l(i.finally(function(){return n&&(r.finallyList=r.finallyList.filter(function(n){return n!==e})),e()}),r)},cancel:function(){r.isCanceled=!0;for(var n=0,e=[r.onCancelList,r.finallyList];n<e.length;n++){var i=e[n];if(i)for(;i.length;){var t=i.shift();"function"==typeof t&&t()}}},isCanceled:function(){return!0===r.isCanceled}};return{then:n.then.bind(void 0),catch:n.catch.bind(void 0),finally:n.finally.bind(void 0),cancel:n.cancel.bind(void 0),isCanceled:n.isCanceled.bind(void 0)}}function e(n){return l(n,{})}function i(i){var t=[];return l(new Promise(function(n,e){return i(n,e,function(n){t.push(n)})}),{onCancelList:t})}Object.defineProperty(n,"__esModule",{value:!0}),n.cancelable=e,n.CancelablePromise=i,n.default=void 0,i.all=function(n){return e(Promise.all(n))},i.allSettled=function(n){return e(Promise.allSettled(n))},i.race=function(n){return e(Promise.race(n))},i.resolve=function(n){return e(Promise.resolve(n))},i.reject=function(n){return e(Promise.reject(n))},n.default=i}); |
{ | ||
"name": "cancelable-promise", | ||
"version": "3.1.3", | ||
"version": "3.2.0", | ||
"description": "A simple cancelable promise", | ||
@@ -5,0 +5,0 @@ "main": "dist/CancelablePromise.js", |
@@ -107,10 +107,21 @@ # cancelable-promise | ||
/** | ||
* @param {(resolve, reject) => void} arg - a promise executor | ||
* @param {(resolve, reject, onCancel) => void} arg - an augmented promise executor | ||
* @returns {CancelablePromise} | ||
*/ | ||
new CancelablePromise((resolve, reject) => { | ||
resolve('ok'); | ||
const promise = new CancelablePromise((resolve, reject, onCancel) => { | ||
const worker = new Worker('some-script.js'); | ||
onCancel(() => { | ||
worker.terminate(); | ||
}); | ||
worker.onmessage = (event) => resolve(event.data); | ||
worker.onerror = (error) => reject(error); | ||
}); | ||
promise.cancel(); // It will execute the callback passed to onCancel | ||
``` | ||
_`onCancel` callback is working as in [p-cancelable](https://github.com/sindresorhus/p-cancelable)_ | ||
### CancelablePromise.cancel | ||
@@ -134,2 +145,44 @@ | ||
### CancelablePromise.finally | ||
```javascript | ||
/** | ||
* @param {() => void} onFinally callback | ||
* @param {boolean} runWhenCanceled force finally execution on cancel | ||
* @returns {void} | ||
*/ | ||
cancelablePromise.finally(() => {}); | ||
// You can release prematurely resources for a long running task | ||
// by forcing finnaly callback execution when cancelling a promise | ||
let worker; | ||
const promise = cancelable( | ||
new Promise((resolve, reject) => { | ||
worker = new Worker('some-script.js'); | ||
worker.onmessage = (event) => { | ||
resolve(event.data); // never executed | ||
}; | ||
worker.onerror = (error) => { | ||
reject(error); // never executed | ||
}; | ||
}) | ||
) | ||
.then(() => { | ||
console.log('never logged'); | ||
}) | ||
.finally( | ||
() => { | ||
console.log('executed'); | ||
if (worker) { | ||
worker.terminate(); | ||
worker = null; | ||
} | ||
}, | ||
// runWhenCanceled boolean | ||
true | ||
); | ||
promise.cancel(); | ||
``` | ||
### Static methods | ||
@@ -136,0 +189,0 @@ |
@@ -1,4 +0,5 @@ | ||
type PromiseExecutor<T> = ( | ||
type CancelablePromiseExecutor<T> = ( | ||
resolve: (value?: T | PromiseLike<T>) => void, | ||
reject: (reason?: any) => void | ||
reject: (reason?: any) => void, | ||
onCancel: (cancelHandler: () => void) => void | ||
) => void; | ||
@@ -57,3 +58,4 @@ | ||
finally( | ||
onfinally?: (() => void) | undefined | null | ||
onfinally?: (() => void) | undefined | null, | ||
runWhenCanceled?: boolean | ||
): CancelablePromiseType<T>; | ||
@@ -73,4 +75,4 @@ | ||
*/ | ||
new <T1>(executorOrPromise: PromiseExecutor<T1>): CancelablePromiseType<T1>; | ||
<T1>(executorOrPromise: PromiseExecutor<T1>): CancelablePromiseType<T1>; | ||
new <T1>(executor: CancelablePromiseExecutor<T1>): CancelablePromiseType<T1>; | ||
<T1>(executor: CancelablePromiseExecutor<T1>): CancelablePromiseType<T1>; | ||
@@ -77,0 +79,0 @@ /** |
@@ -12,40 +12,83 @@ function createCallback(onResult, options) { | ||
function thenFunc(options, onSuccess, onError) { | ||
return cancelable( | ||
this.then( | ||
createCallback(onSuccess, options), | ||
createCallback(onError, options) | ||
), | ||
options | ||
); | ||
} | ||
function makeCancelable(promise, options) { | ||
const methods = { | ||
then(onSuccess, onError) { | ||
return makeCancelable( | ||
promise.then( | ||
createCallback(onSuccess, options), | ||
createCallback(onError, options) | ||
), | ||
options | ||
); | ||
}, | ||
function catchFunc(options, onError) { | ||
return cancelable(this.catch(createCallback(onError, options)), options); | ||
} | ||
catch(onError) { | ||
return makeCancelable( | ||
promise.catch(createCallback(onError, options)), | ||
options | ||
); | ||
}, | ||
function finallyFunc(options, onFinally) { | ||
return cancelable(this.finally(onFinally), options); | ||
} | ||
finally(onFinally, runWhenCanceled) { | ||
if (runWhenCanceled) { | ||
if (!options.finallyList) { | ||
options.finallyList = []; | ||
} | ||
options.finallyList.push(onFinally); | ||
} | ||
return makeCancelable( | ||
promise.finally(() => { | ||
if (runWhenCanceled) { | ||
options.finallyList = options.finallyList.filter( | ||
(callback) => callback !== onFinally | ||
); | ||
} | ||
return onFinally(); | ||
}), | ||
options | ||
); | ||
}, | ||
function cancelFunc(options) { | ||
options.isCanceled = true; | ||
} | ||
cancel() { | ||
options.isCanceled = true; | ||
for (const callbacks of [options.onCancelList, options.finallyList]) { | ||
if (callbacks) { | ||
while (callbacks.length) { | ||
const onCancel = callbacks.shift(); | ||
if (typeof onCancel === 'function') { | ||
onCancel(); | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
function isCanceled(options) { | ||
return options.isCanceled; | ||
} | ||
isCanceled() { | ||
return options.isCanceled === true; | ||
}, | ||
}; | ||
export function cancelable(promise, options = { isCanceled: false }) { | ||
return { | ||
then: thenFunc.bind(promise, options), | ||
catch: catchFunc.bind(promise, options), | ||
finally: finallyFunc.bind(promise, options), | ||
cancel: cancelFunc.bind(promise, options), | ||
isCanceled: isCanceled.bind(promise, options), | ||
then: methods.then.bind(undefined), | ||
catch: methods.catch.bind(undefined), | ||
finally: methods.finally.bind(undefined), | ||
cancel: methods.cancel.bind(undefined), | ||
isCanceled: methods.isCanceled.bind(undefined), | ||
}; | ||
} | ||
export function cancelable(promise) { | ||
return makeCancelable(promise, {}); | ||
} | ||
export function CancelablePromise(executor) { | ||
return cancelable(new Promise(executor)); | ||
const onCancelList = []; | ||
return makeCancelable( | ||
new Promise((resolve, reject) => { | ||
return executor(resolve, reject, (onCancel) => { | ||
onCancelList.push(onCancel); | ||
}); | ||
}), | ||
{ onCancelList } | ||
); | ||
} | ||
@@ -52,0 +95,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
44506
768
251