Mooeypoo has uploaded a new change for review. https://gerrit.wikimedia.org/r/295565
Change subject: Add a PromisePrioritizer and use it for notifications fetching ...................................................................... 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 --- M Resources.php M modules/api/mw.echo.api.EchoApi.js A modules/api/mw.echo.api.PromisePrioritizer.js M modules/ui/mw.echo.ui.NotificationsInboxWidget.js 4 files changed, 94 insertions(+), 10 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Echo refs/changes/65/295565/1 diff --git a/Resources.php b/Resources.php index 84bf1b0..0f0e7cb 100644 --- a/Resources.php +++ b/Resources.php @@ -196,6 +196,7 @@ 'ext.echo.api' => $echoResourceTemplate + array( 'scripts' => array( 'api/mw.echo.api.js', + 'api/mw.echo.api.PromisePrioritizer.js', 'api/mw.echo.api.EchoApi.js', 'api/mw.echo.api.APIHandler.js', 'api/mw.echo.api.LocalAPIHandler.js', diff --git a/modules/api/mw.echo.api.EchoApi.js b/modules/api/mw.echo.api.EchoApi.js index a37a0b7..4bc290e 100644 --- a/modules/api/mw.echo.api.EchoApi.js +++ b/modules/api/mw.echo.api.EchoApi.js @@ -15,6 +15,7 @@ this.fetchingPromise = null; this.limit = config.limit || 25; + this.fetchingPrioritizer = new mw.echo.api.PromisePrioritizer(); }; OO.initClass( mw.echo.api.EchoApi ); @@ -142,15 +143,17 @@ return $.Deferred().reject().promise(); } - return handler.fetchNotifications( + return this.fetchingPrioritizer.prioritize( handler.fetchNotifications( type, // For the remote source, we are fetching 'local' notifications 'local', !!isForced, this.convertFiltersToAPIParams( filters ) - ) - .then( function ( result ) { - return OO.getProp( result.query, 'notifications' ); + ) ) + .then( function ( promise ) { + return promise.then( function ( result ) { + return OO.getProp( result.query, 'notifications' ); + } ); } ); }; @@ -172,14 +175,16 @@ [ sources ] : 'local'; - return this.network.getApiHandler( 'local' ).fetchNotifications( + return this.fetchingPrioritizer.prioritize( this.network.getApiHandler( 'local' ).fetchNotifications( type, sources, isForced, this.convertFiltersToAPIParams( filters ) - ) - .then( function ( result ) { - return OO.getProp( result.query, 'notifications' ); + ) ) + .then( function ( promise ) { + return promise.then( function ( result ) { + return OO.getProp( result.query, 'notifications' ); + } ); } ); }; diff --git a/modules/api/mw.echo.api.PromisePrioritizer.js b/modules/api/mw.echo.api.PromisePrioritizer.js new file mode 100644 index 0000000..dd23536 --- /dev/null +++ b/modules/api/mw.echo.api.PromisePrioritizer.js @@ -0,0 +1,78 @@ +( function ( mw, $ ) { + /** + * Promise prioritizer for API actions. The prioritizer takes + * multiple promises but ignores the previous ones until one is + * either resolved or rejected. + * + * 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 MwEchoDmPromisePrioritizer() { + this.deferred = $.Deferred(); + this.promise = null; + }; + + /* Initialization */ + + OO.initClass( mw.echo.api.PromisePrioritizer ); + + /** + * Prioritize a promise + * + * @param {[type]} 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 main deferred object is resolved with + * the latest prioritized promse. + */ + mw.echo.api.PromisePrioritizer.prototype.setSuccess = function ( promise ) { + if ( this.promise === promise ) { + this.deferred.resolve( this.promise ); + + this.promise = null; + this.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 main deferred object is rejected with + * the latest prioritized promse. + */ + mw.echo.api.PromisePrioritizer.prototype.setFailure = function ( promise ) { + if ( this.promise === promise ) { + this.deferred.reject( this.promise ); + + this.promise = null; + this.deferred = $.Deferred(); + } + }; +} )( mediaWiki, jQuery ); diff --git a/modules/ui/mw.echo.ui.NotificationsInboxWidget.js b/modules/ui/mw.echo.ui.NotificationsInboxWidget.js index a36d9d4..1a38357 100644 --- a/modules/ui/mw.echo.ui.NotificationsInboxWidget.js +++ b/modules/ui/mw.echo.ui.NotificationsInboxWidget.js @@ -205,7 +205,7 @@ */ mw.echo.ui.NotificationsInboxWidget.prototype.pushPending = function () { this.noticeMessageWidget.toggle( false ); - this.readStateSelectWidget.setDisabled( true ); + // this.readStateSelectWidget.setDisabled( true ); this.topPaginationWidget.setDisabled( true ); this.bottomPaginationWidget.setDisabled( true ); @@ -218,7 +218,7 @@ */ mw.echo.ui.NotificationsInboxWidget.prototype.popPending = function () { this.resetMessageLabel(); - this.readStateSelectWidget.setDisabled( false ); + // this.readStateSelectWidget.setDisabled( false ); this.topPaginationWidget.setDisabled( false ); this.bottomPaginationWidget.setDisabled( false ); -- To view, visit https://gerrit.wikimedia.org/r/295565 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I698a2b8eced6d8ee997efef353697d27d92cfb2f Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Echo Gerrit-Branch: master Gerrit-Owner: Mooeypoo <mor...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits