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

Reply via email to