Skip to content

Instantly share code, notes, and snippets.

@WebReflection
Last active August 29, 2015 14:18
Show Gist options
  • Save WebReflection/0ca8fac8013f76fb4d06 to your computer and use it in GitHub Desktop.
Save WebReflection/0ca8fac8013f76fb4d06 to your computer and use it in GitHub Desktop.
An alternative playground with cancel-able Promises that rejects through arbitrary value
(function (Object, Original) {'use strict';
// (C) Andrea Giammarchi - WTFPL
OP = Original.prototype;
if ('cancel' in OP) return;
var
OP,
$then = OP.then,
$catch = OP.catch,
defineProperty = Object.defineProperty,
defineProperties = Object.defineProperties,
// noop = function () {},
createDescriptors = function (cancel) {
var descriptors = {
'cancel': {value: function () {
// this.catch(noop);
return cancel.apply(this, arguments);
}},
'then': {value: function (ok, err) {
var args = arguments.length === 2 ? [ok, err] : [ok];
if (typeof ok === 'function') args[0] = function () {
var r = ok.apply(this, arguments);
if (
r instanceof Original &&
r.hasOwnProperty('cancel')
) {
cancel = r.cancel;
}
return r;
};
return defineProperties(
$then.apply(this, args),
descriptors
);
}},
'catch': {value: function () {
return defineProperties(
$catch.apply(this, arguments),
descriptors
);
}}
};
return descriptors;
}
;
function Promise(callback) {
var
resolve, reject, cancel,
state = 'pending',
p = new Original(function ($resolve, $reject) {
resolve = $resolve;
reject = $reject;
})
;
callback(
function () {
if (state === 'pending') {
state = 'resolved';
resolve.apply(this, arguments);
}
},
function () {
if (state === 'pending') {
state = 'rejected';
reject.apply(this, arguments);
}
},
function (howToCancel) {
if (typeof howToCancel !== 'function') {
throw new Error('Unable to cancel this promise');
}
return cancel || (cancel = function () {
if (state === 'pending') {
state = 'canceled';
howToCancel.apply(this, arguments);
reject.apply(this, arguments);
return this;
}
});
}
);
return cancel ? defineProperties(p, createDescriptors(cancel)) : p;
}
Object.getOwnPropertyNames(Original).forEach(function (name) {
if (!(name in Promise)) {
defineProperty(
Promise,
name,
Object.getOwnPropertyDescriptor(Original, name)
);
}
});
Promise.prototype = OP;
defineProperty(OP, 'cancel', {
configurable: true,
enumerable: false,
writable: true,
value: function () { return this; }
});
try {
module.exports = Promise;
} catch(e) {
this.Promise = Promise;
}
}.call(this, Object, Promise));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment