Skip to content

Instantly share code, notes, and snippets.

@ismasan
Last active December 26, 2015 12:39
Show Gist options
  • Save ismasan/7152847 to your computer and use it in GitHub Desktop.
Save ismasan/7152847 to your computer and use it in GitHub Desktop.
/**
* Multipromise
*
* A jQuery.Deferred() - like promise implementation
* that supports adding multiple child promises to it.
* done / fail callbacks will trigger multiple times as child promises are resolved / rejected
* Useful for streaming promise-based data flows
*
* Example
*
* m = new MultiPromise()
* p1 = $.Deferred()
* p1.done(function (a){console.log('p1 resolved with ', a)})
* p2 = $.Deferred()
* p2.done(function (a){console.log('p2 resolved with ', a)})
* m.push(p1)
* m.push(p2)
* m.resolve('lalala') // resolves p1 and p2
* p3 = $.Deferred()
* p3.done(function (a){console.log('p3 resolved with ', a)})
* m.push(p3) // p3 resolves immediatly because m is already resolved
*/
var MultiPromise = (function () {
function toArray(args, i) {
i = i || 0;
return Array.prototype.slice.call(args, i)
}
MultiPromise = function () {
this._promises = []
this._doneCallbacks = []
this._failCallbacks = []
this._state = 'pending'
this.this_args = []
}
MultiPromise.prototype = {
push: function (promise) {
this._promises.push(promise)
promise.done(this._done.bind(this))
promise.fail(this._fail.bind(this))
if(this.isResolved()) this.resolve()
if(this.isRejected()) this.reject()
},
done: function (fn) {
this._doneCallbacks.push(fn)
return this
},
fail: function (fn) {
this._failCallbacks.push(fn)
return this
},
resolve: function () {
this._state = 'resolved'
var self = this
if(arguments.length > 0) self._args = toArray(arguments)
this._promises.forEach(function (pr) {
pr.resolve.call(pr, self._args)
})
return this
},
reject: function () {
this._state = 'rejected'
var self = this
if(arguments.length > 0) self._args = toArray(arguments)
this._promises.forEach(function (pr) {
pr.reject.call(pr, self._args)
})
return this
},
resolveWith: $.noop,
rejectWith: $.noop,
notifyWith: $.noop,
progressWith: $.noop,
_done: function () {
var args = toArray(arguments)
this._doneCallbacks.forEach(function (fn) {
fn.call(null, args)
})
},
_fail: function () {
var args = toArray(arguments)
this._failCallbacks.forEach(function (fn) {
fn.call(null, args)
})
},
promise: function () { return this; },
always: function (fn) {
this.done(fn)
this.fail(fn)
},
notify: $.noop,
then: function (resolvedFn, rejectedFn, progressFn) {
if(resolvedFn) this.done(resolvedFn)
if(rejectedFn) this.done(rejectedFn)
if(progressFn) this.done(progressFn)
return this
},
isResolved: function () {
return this._state == 'resolved'
},
isRejected: function () {
return this._state == 'rejected'
}
}
return MultiPromise
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment