Last active
January 2, 2016 11:09
-
-
Save sukima/8294488 to your computer and use it in GitHub Desktop.
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
// PinkySwear - Minimalistic implementation of the Promises/A+ spec | |
// | |
// Public Domain. Use, modify and distribute it any way you like. No attribution required. | |
// | |
// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. | |
// | |
// https://github.com/timjansen/PinkySwear.js | |
// | |
// Modified to add resolve/reject/notify/process/fin/done/fail/get/invoke methods | |
(function(target) { | |
/* jshint eqnull:true */ | |
function isFunction(f,o) { return typeof f == 'function'; } | |
function defer(callback) { setTimeout(callback, 0); } | |
target[0][target[1]] = function pinkySwear() { | |
var state; // undefined/null = pending, true = fulfilled, false = rejected | |
var values = []; // an array of values as arguments for the then() handlers | |
var deferred = []; // functions to call when set() is invoked | |
var progress_fns; // functions to call when notify() is invoked | |
var set = function promise(newState, newValues) { | |
if (state == null) { | |
state = newState; | |
values = newValues; | |
defer(function() { | |
for (var i = 0; i < deferred.length; i++) | |
deferred[i](); | |
}); | |
} | |
}; | |
set.then = function(onFulfilled, onRejected, onProgress) { | |
var newPromise = pinkySwear(); | |
newPromise.progress = function(v) { set.progress(v); return newPromise; }; | |
newPromise.notify = function(v) { set.notify(v); return newPromise; }; | |
var callCallbacks = function() { | |
try { | |
var f = (state ? onFulfilled : onRejected); | |
if (isFunction(f)) { | |
var r = f.apply(null, values); | |
if (r && isFunction(r.then)) | |
r.then( | |
function(value){newPromise(true, [value]);}, | |
function(value){newPromise(false, [value]);}, | |
function(value){newPromise.notify(value);} | |
); | |
else | |
newPromise(true, [r]); | |
} | |
else | |
newPromise(state, values); | |
} | |
catch (e) { | |
newPromise(false, [e]); | |
} | |
}; | |
if (state != null) | |
defer(callCallbacks); | |
else | |
deferred.push(callCallbacks); | |
if (isFunction(onProgress)) | |
set.progress(onProgress); | |
return newPromise; | |
}; | |
set.notify = function(value) { | |
if (state == null) | |
defer(function() { | |
if (progress_fns != null) | |
for (var i = 0; i < progress_fns.length; i++) | |
progress_fns[i](value); | |
}); | |
}; | |
set.resolve = function(value) { set(true, [value]); }; | |
set.reject = function(value) { set(false, [value]); }; | |
set.progress = function(onProgress) { | |
if (progress_fns == null) { progress_fns = []; } | |
progress_fns.push(onProgress); | |
return set; | |
}; | |
// always(func) is the same as then(func, func) | |
set.always = function(func) { return set.then(func, func); }; | |
// fin(func) is like always() but doesn't modify the promise chain | |
set.fin = function(func) { set.then(func, func); return set; }; | |
// error(func) is the same as then(0, func) | |
set.error = set.fail = function(func) { return set.then(0, func); }; | |
function handleUncaughtExceptions() { | |
if (state === false) { | |
throw (values.length > 1) ? values : values[0]; | |
} | |
} | |
set.done = function(onFulfilled, onRejected, onProgress) { | |
if (onFulfilled || onRejected || onProgress) { | |
set.then(onFulfilled, onRejected, onProgress).done(); | |
return; | |
} | |
if (state != null) | |
defer(handleUncaughtExceptions); | |
else | |
deferred.push(handleUncaughtExceptions); | |
}; | |
set.get = function(prop) { | |
return set.then(function(value) { return value[prop]; }); | |
}; | |
set.invoke = function(prop) { | |
var args = [].slice.call(arguments, 1) || []; | |
return set.then(function(value) { return value[prop].apply(value, args); }); | |
}; | |
return set; | |
} | |
return pinkySwear; | |
})(typeof module === 'undefined' ? [this, 'pinkySwear'] : [module, 'exports']); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment