Sets out a pattern for chaining methods and implementing native promises alongside a polyfill for unsupported browsers.
/* | |
* referenced Jake Archibald's http://www.html5rocks.com/en/tutorials/es6/promises/ | |
*/ | |
(function(window, undefined){ | |
window.chainit = function() | |
{ | |
function Initialize() | |
{ | |
this.methodpromise = new Promise(DoStuff); //-- initialize | |
this.error = false; | |
}; | |
function DoStuff(resolve, reject) | |
{ | |
//-- do what you want, resolve or reject the initial promise | |
resolve('initial complete'); | |
//reject('initial fail'); | |
} | |
//-- chained methods process. simply cycle through the parameters/arguments | |
//-- if an async action takes place and a "promise" is returned the chain | |
//-- will fire in sequence, bit cleaner than using a Deferred method | |
function PromiseFactory() | |
{ | |
for(var i=0; i<arguments.length; i++) | |
{ | |
var value = arguments[i], | |
self = this, | |
funcarray = []; | |
if(!value) | |
{ | |
continue; | |
} | |
if( {}.toString.call(value) === '[object Function]' ) //-- check "success/failure" function combo | |
{ | |
funcarray.push(_lame(value, this)); | |
} | |
else | |
{ | |
for(var k=0; k<value.length; k++) | |
{ | |
var subvalue = value[k]; | |
if(subvalue) | |
{ | |
funcarray.push(_lame(subvalue, this, k)); | |
} | |
} | |
} | |
this.methodpromise = this.methodpromise.then.apply(this.methodpromise, funcarray); | |
} | |
function _lame( value, context, index ) | |
{ | |
return function() | |
{ | |
if(!context.error) | |
{ | |
if(index > 0) | |
{ | |
context.error = true; | |
} | |
return value.apply(context, arguments); | |
} | |
//console.log('technically still firing'); | |
}; | |
} | |
} | |
//-- | |
Initialize.prototype = | |
{ | |
complete: function() | |
{ | |
PromiseFactory.call(this, arguments); | |
return this; | |
}, | |
amethod: function(before, after) | |
{ | |
PromiseFactory.call(this, before, after); | |
return this; | |
} | |
}; | |
return new Initialize(); | |
}; | |
})(this); |
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<title>JS.Chaining & Native Promises</title> | |
</head> | |
<body> | |
<div> | |
<!-- Begin Body - - - - - - - - - - - - - - - - - - - - - - - - - - --> | |
<h1>JS.Chaining & Native Promises</h1> | |
<p> | |
Sets out a pattern for chaining methods and implementing native promises alongside a polyfill for unsupported browsers. | |
</p> | |
<!-- End Body - - - - - - - - - - - - - - - - - - - - - - - - - - --> | |
</div> | |
<!-- | |
https://github.com/jakearchibald/es6-promise#readme | |
implement the polyfill for pretty much non Chrome, | |
maybe Opera, and it seemed to be needed for Firefox 27 | |
despite documentation to the contrary | |
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise | |
--> | |
<script> | |
!function(){var a,b,c,d;!function(){var e={},f={};a=function(a,b,c){e[a]={deps:b,callback:c}},d=c=b=function(a){function c(b){if("."!==b.charAt(0))return b;for(var c=b.split("/"),d=a.split("/").slice(0,-1),e=0,f=c.length;f>e;e++){var g=c[e];if(".."===g)d.pop();else{if("."===g)continue;d.push(g)}}return d.join("/")}if(d._eak_seen=e,f[a])return f[a];if(f[a]={},!e[a])throw new Error("Could not find module "+a);for(var g,h=e[a],i=h.deps,j=h.callback,k=[],l=0,m=i.length;m>l;l++)"exports"===i[l]?k.push(g={}):k.push(b(c(i[l])));var n=j.apply(this,k);return f[a]=g||n}}(),a("promise/all",["./utils","exports"],function(a,b){"use strict";function c(a){var b=this;if(!d(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){f(a,b)}}function f(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;j<a.length;j++)g=a[j],g&&e(g.then)?g.then(d(j),c):f(j,g)})}var d=a.isArray,e=a.isFunction;b.all=c}),a("promise/asap",["exports"],function(a){"use strict";function b(){return function(){process.nextTick(e)}}function c(){var a=0,b=new i(e),c=document.createTextNode("");return b.observe(c,{characterData:!0}),function(){c.data=a=++a%2}}function d(){return function(){j.setTimeout(e,1)}}function e(){for(var a=0;a<k.length;a++){var b=k[a],c=b[0],d=b[1];c(d)}k=[]}function f(a,b){var c=k.push([a,b]);1===c&&g()}var g,h="undefined"!=typeof window?window:{},i=h.MutationObserver||h.WebKitMutationObserver,j="undefined"!=typeof global?global:this,k=[];g="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?b():i?c():d(),a.asap=f}),a("promise/cast",["exports"],function(a){"use strict";function b(a){if(a&&"object"==typeof a&&a.constructor===this)return a;var b=this;return new b(function(b){b(a)})}a.cast=b}),a("promise/config",["exports"],function(a){"use strict";function b(a,b){return 2!==arguments.length?c[a]:(c[a]=b,void 0)}var c={instrument:!1};a.config=c,a.configure=b}),a("promise/polyfill",["./promise","./utils","exports"],function(a,b,c){"use strict";function d(){var a="Promise"in window&&"cast"in window.Promise&&"resolve"in window.Promise&&"reject"in window.Promise&&"all"in window.Promise&&"race"in window.Promise&&function(){var a;return new window.Promise(function(b){a=b}),f(a)}();a||(window.Promise=e)}var e=a.Promise,f=b.isFunction;c.polyfill=d}),a("promise/promise",["./config","./utils","./cast","./all","./race","./resolve","./reject","./asap","exports"],function(a,b,c,d,e,f,g,h,i){"use strict";function j(a){if(!w(a))throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");if(!(this instanceof j))throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");this._subscribers=[],k(a,this)}function k(a,b){function c(a){p(b,a)}function d(a){r(b,a)}try{a(c,d)}catch(e){d(e)}}function l(a,b,c,d){var e,f,g,h,i=w(c);if(i)try{e=c(d),g=!0}catch(j){h=!0,f=j}else e=d,g=!0;o(b,e)||(i&&g?p(b,e):h?r(b,f):a===F?p(b,e):a===G&&r(b,e))}function m(a,b,c,d){var e=a._subscribers,f=e.length;e[f]=b,e[f+F]=c,e[f+G]=d}function n(a,b){for(var c,d,e=a._subscribers,f=a._detail,g=0;g<e.length;g+=3)c=e[g],d=e[g+b],l(b,c,d,f);a._subscribers=null}function o(a,b){var c,d=null;try{if(a===b)throw new TypeError("A promises callback cannot return that same promise.");if(v(b)&&(d=b.then,w(d)))return d.call(b,function(d){return c?!0:(c=!0,b!==d?p(a,d):q(a,d),void 0)},function(b){return c?!0:(c=!0,r(a,b),void 0)}),!0}catch(e){return c?!0:(r(a,e),!0)}return!1}function p(a,b){a===b?q(a,b):o(a,b)||q(a,b)}function q(a,b){a._state===D&&(a._state=E,a._detail=b,u.async(s,a))}function r(a,b){a._state===D&&(a._state=E,a._detail=b,u.async(t,a))}function s(a){n(a,a._state=F)}function t(a){n(a,a._state=G)}var u=a.config,v=(a.configure,b.objectOrFunction),w=b.isFunction,x=(b.now,c.cast),y=d.all,z=e.race,A=f.resolve,B=g.reject,C=h.asap;u.async=C;var D=void 0,E=0,F=1,G=2;j.prototype={constructor:j,_state:void 0,_detail:void 0,_subscribers:void 0,then:function(a,b){var c=this,d=new this.constructor(function(){});if(this._state){var e=arguments;u.async(function(){l(c._state,d,e[c._state-1],c._detail)})}else m(this,d,a,b);return d},"catch":function(a){return this.then(null,a)}},j.all=y,j.cast=x,j.race=z,j.resolve=A,j.reject=B,i.Promise=j}),a("promise/race",["./utils","exports"],function(a,b){"use strict";function c(a){var b=this;if(!d(a))throw new TypeError("You must pass an array to race.");return new b(function(b,c){for(var d,e=0;e<a.length;e++)d=a[e],d&&"function"==typeof d.then?d.then(b,c):b(d)})}var d=a.isArray;b.race=c}),a("promise/reject",["exports"],function(a){"use strict";function b(a){var b=this;return new b(function(b,c){c(a)})}a.reject=b}),a("promise/resolve",["exports"],function(a){"use strict";function b(a){var b=this;return new b(function(b){b(a)})}a.resolve=b}),a("promise/utils",["exports"],function(a){"use strict";function b(a){return c(a)||"object"==typeof a&&null!==a}function c(a){return"function"==typeof a}function d(a){return"[object Array]"===Object.prototype.toString.call(a)}var e=Date.now||function(){return(new Date).getTime()};a.objectOrFunction=b,a.isFunction=c,a.isArray=d,a.now=e}),b("promise/polyfill").polyfill()}(); | |
</script> | |
<script src="chaining-and-native-promises.js"></script> | |
<script> | |
(function(window, undefined){ | |
chainit() | |
.complete( | |
function(a) //-- resolution from the initial promise | |
{ | |
debugger; | |
return "first COMPLETE"; | |
}, | |
function(a) //-- rejection from the initial promise | |
{ | |
debugger; | |
}) | |
.complete( | |
function(a) //-- resolution | |
{ | |
debugger; | |
return new Promise(function(resolve, reject) | |
{ | |
setTimeout(function() | |
{ | |
resolve("second COMPLETE"); | |
},1000); | |
}); | |
}, | |
function(a) //-- rejection | |
{ | |
debugger; | |
}) | |
.amethod( | |
function(a) //-- do something | |
{ | |
debugger; | |
return "something complete"; | |
}, | |
function(a) //-- do another thing | |
{ | |
debugger; | |
return new Promise(function(resolve, reject) | |
{ | |
setTimeout(function() | |
{ | |
//resolve("fourth complete"); | |
reject("fourth FAIL!"); //-- bit of a quirk, will find the next available "rejection" or "kinda" stop | |
}, 3000); | |
}); | |
}) | |
.amethod( | |
function(a) //-- do something | |
{ | |
debugger; | |
return "something complete"; | |
}, | |
function(a) //-- do another thing | |
{ | |
debugger; | |
return new Promise(function(resolve, reject) | |
{ | |
setTimeout(function() | |
{ | |
reject("fifth FAIL!"); | |
}, 3000); | |
}); | |
}) | |
.complete( | |
function(a) //-- resolution | |
{ | |
debugger; | |
return Promise.resolve("sixth complete, finished!"); | |
}, | |
function(a) //-- rejection | |
{ | |
debugger; | |
} | |
) | |
.complete(function(a) //-- resolution | |
{ | |
debugger; | |
}); | |
})(this); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment