Last active
August 29, 2015 13:57
-
-
Save eduardolundgren/9785720 to your computer and use it in GitHub Desktop.
CancellablePromise.all
This file contains 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
/** | |
* Cancellable promise. | |
* | |
* @class CancellablePromise | |
* @constructor | |
* @extends {Promise} | |
* @param {Function} fn A function where to insert the logic that resolves this | |
* promise. Receives `fulfill` and `reject` functions as parameters. This | |
* function is called synchronously. | |
* @param {Function} opt_errorCallback Optional error callback to be fired | |
* whenever a cancellable promise is cancelled. | |
*/ | |
function CancellablePromise(fn, opt_errorCallback) { | |
CancellablePromise.superclass.constructor.apply(this, arguments); | |
this._errorCallback = opt_errorCallback; | |
} | |
A.extend(CancellablePromise, A.Promise, { | |
/** | |
* Cancels the Promise by rejecting it with a cancel Error. No action is | |
* performed if the Promise is already resolved. | |
* | |
* @method cancel | |
* @param {String} opt_message An optional debugging message for describing | |
* the cancellation reason. | |
*/ | |
cancel: function(opt_message) { | |
var error = new A.CancellablePromise.Error(opt_message); | |
try { | |
if (this._errorCallback) { | |
this._errorCallback(error); | |
} | |
} | |
catch (e) { | |
this._resolver.reject(e); | |
return; | |
} | |
this._resolver.reject(error); | |
}, | |
then: function() { | |
var instance = this, | |
promise = CancellablePromise.superclass.then.apply(this, arguments); | |
promise.cancel = A.bind(instance.cancel, instance); | |
return promise; | |
} | |
}); | |
/* | |
* Returns a cancellable promise that is resolved or rejected when all values | |
* are resolved or any is rejected. This is useful for waiting for the | |
* resolution of multiple promises, such as reading multiple files in Node.js or | |
* making multiple XHR requests in the browser. | |
* | |
* @method all | |
* @param {Any[]} values An array of any kind of values, promises or not. If a | |
* value is not | |
* @return {CancellablePromise} A promise for an array of all the fulfillment values | |
* @static | |
*/ | |
CancellablePromise.all = function(values) { | |
var CancellablePromise = this, | |
children = []; | |
return new CancellablePromise(function(resolve, reject) { | |
if (!A.Lang.isArray(values)) { | |
reject(new TypeError('CancellablePromise.all expects an array of values or promises')); | |
return; | |
} | |
var remaining = values.length, | |
i = 0, | |
length = values.length, | |
results = [], | |
child; | |
function oneDone(index) { | |
return function(value) { | |
results[index] = value; | |
remaining--; | |
if (!remaining) { | |
resolve(results); | |
} | |
}; | |
} | |
if (length < 1) { | |
return resolve(results); | |
} | |
for (; i < length; i++) { | |
child = CancellablePromise.resolve(values[i]); | |
child.then(oneDone(i), reject); | |
children.push(child); | |
} | |
}).then(function(result) { | |
children = null; | |
return result; | |
}, | |
function(reason) { | |
A.Array.invoke(children, 'cancel'); | |
children = null; | |
throw reason; | |
}); | |
}; | |
/* | |
* Ensures that a certain value is a cancellable promise. If it is not a | |
* promise, it wraps it in one. | |
* | |
* @method resolve | |
* @param {Any} Any object that may or may not be a promise | |
* @return {CancellablePromise} | |
* @static | |
*/ | |
CancellablePromise.resolve = A.Promise.resolve; | |
/* | |
* A shorthand for creating a rejected cancellable promise. | |
* | |
* @method reject | |
* @param {Any} reason Reason for the rejection of this promise. Usually an | |
* Error Object | |
* @return {CancellablePromise} A rejected promise | |
* @static | |
*/ | |
CancellablePromise.reject = A.Promise.reject; | |
A.CancellablePromise = CancellablePromise; | |
/** | |
* Error used as a rejection reason for canceled Promises. | |
* | |
* @class Promise.CancellationError | |
* @constructor | |
* @extends {Error} | |
* @param {String} opt_message An optional debugging message for describing the | |
* cancellation reason. | |
*/ | |
function CancellationError(opt_message) { | |
CancellationError.superclass.constructor.apply(this, arguments); | |
this.message = opt_message; | |
} | |
A.extend(CancellationError, Error, { | |
name: 'cancel' | |
}); | |
A.CancellablePromise.Error = CancellationError; |
This file contains 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
var delay = function(ms) { | |
var timeout; | |
return new Y.CancellablePromise( | |
function(resolve) { | |
timeout = setTimeout(function() { | |
resolve(); | |
}, ms); | |
}, | |
function() { | |
clearTimeout(timeout); | |
console.log('Delay cancelled by a CancellationError.'); | |
} | |
); | |
}; | |
var all = Y.CancellablePromise.all([delay(3000), delay(4000)]).then( | |
function() { | |
console.log('Y.CancellablePromise.all done'); | |
}, | |
function(reason) { | |
console.log('Y.CancellablePromise.all rejectd', reason); | |
throw reason; | |
}); | |
all.cancel(); |
This file contains 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
var delay = function(ms) { | |
var timeout; | |
return new Y.CancellablePromise(function(resolve) { | |
timeout = setTimeout(function() { | |
resolve(); | |
}, ms); | |
}) | |
.then( | |
function() { | |
console.log('delay done'); | |
}, | |
function(reason) { | |
if (reason instanceof Y.CancellablePromise.Error) { | |
clearTimeout(timeout); | |
console.log('Delay cancelled by a CancellationError.'); | |
} | |
throw reason; | |
} | |
); | |
}; | |
var all = Y.CancellablePromise.all([delay(3000), delay(4000)]).then( | |
function() { | |
console.log('Y.CancellablePromise.all done'); | |
}, | |
function(reason) { | |
console.log('Y.CancellablePromise.all rejectd', reason); | |
throw reason; | |
}); | |
all.cancel(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment