mediawiki-extensions-Echo/modules/api/mw.echo.api.PromisePrioritizer.js
Moriel Schottlender a1ec29d06a Add a PromisePrioritizer and use it for notifications fetching
This will allow us to let the user click filters quickly, effectively
changing the promises sent to the API, but let the API only resolve
with the latest requested promise.

Bug: T136895
Change-Id: I698a2b8eced6d8ee997efef353697d27d92cfb2f
2016-06-23 14:12:00 -07:00

89 lines
2.5 KiB
JavaScript

( function ( mw, $ ) {
/**
* Promise prioritizer for API actions. The prioritizer takes
* a promise at a time, always prioritizing the latest promise and
* aborting and ignoring the others.
*
* This allows us to send multiple promises in quick successions but
* trust that we get back only the latest successful request.
*
* @class
*
* @constructor
*/
mw.echo.api.PromisePrioritizer = function MwEchoApiPromisePrioritizer() {
this.deferred = $.Deferred();
this.promise = null;
};
/* Initialization */
OO.initClass( mw.echo.api.PromisePrioritizer );
/**
* Prioritize a promise
*
* @param {jQuery.Promise|Promise} promise Promise
* @return {jQuery.Promise} The main deferred object that resolves
* or rejects when the latest promise is resolved or rejected.
*/
mw.echo.api.PromisePrioritizer.prototype.prioritize = function ( promise ) {
var previousPromise = this.promise;
promise
.then(
this.setSuccess.bind( this, promise ),
this.setFailure.bind( this, promise )
);
this.promise = promise;
if ( previousPromise && previousPromise.abort ) {
previousPromise.abort();
}
return this.deferred.promise();
};
/**
* Set success for the promise. Resolve the main deferred object only
* if we are dealing with the currently prioritized promise.
*
* @param {jQuery.Promise} promise The promise that resolved successfully.
* The main deferred object is resolved with the result of the
* latest prioritized promise.
*/
mw.echo.api.PromisePrioritizer.prototype.setSuccess = function ( promise ) {
var prioritizer = this;
if ( this.promise === promise ) {
this.promise.done( function () {
prioritizer.deferred.resolve.apply( prioritizer.deferred, arguments );
prioritizer.promise = null;
prioritizer.deferred = $.Deferred();
} );
}
};
/**
* Set failure for the promise. Reject the main deferred object only
* if we are dealing with the currently prioritized promise.
*
* @param {jQuery.Promise} promise The promise that failed.
* The main deferred object is rejected with the result of the
* latest prioritized promise
*/
mw.echo.api.PromisePrioritizer.prototype.setFailure = function ( promise ) {
var prioritizer = this;
if ( this.promise === promise ) {
this.promise.fail( function () {
prioritizer.deferred.reject.apply( prioritizer.deferred, arguments );
prioritizer.promise = null;
prioritizer.deferred = $.Deferred();
} );
}
};
} )( mediaWiki, jQuery );