mediawiki.api: Use then() in getToken instead of manual Deferred wrapping
authorTimo Tijhof <krinklemail@gmail.com>
Thu, 15 May 2014 00:05:57 +0000 (02:05 +0200)
committerTimo Tijhof <krinklemail@gmail.com>
Thu, 15 May 2014 00:05:57 +0000 (02:05 +0200)
* Use then() instead of done()/fail() with a manually created
  Deferred as wrapper. This also makes the passing on of the
  error more explicit.

* Store promises with an abort handler instead of Deferreds, so
  that we don't need to call "d.promise( { abort: d.abort } )"
  again on each return to re-attach the abort, simply do it right
  the first time. We don't need to store the Deferred's handlers
  since only the closure of the caller needs access to
  resolve/reject it. The cached one only needs to be a promise.

* Rename relevant variables to avoid further confusion.

Change-Id: If8995ede271746580c3f2eb0b4a6ecd79e90c7d5

resources/src/mediawiki.api/mediawiki.api.js

index 5f0b004..dbedb32 100644 (file)
                        }
                },
                // Keyed by ajax url and symbolic name for the individual request
-               deferreds = {};
+               promises = {};
 
-       // Pre-populate with fake ajax deferreds to save http requests for tokens
+       // Pre-populate with fake ajax promises to save http requests for tokens
        // we already have on the page via the user.tokens module (bug 34733).
-       deferreds[ defaultOptions.ajax.url ] = {};
+       promises[ defaultOptions.ajax.url ] = {};
        $.each( mw.user.tokens.get(), function ( key, value ) {
                // This requires #getToken to use the same key as user.tokens.
                // Format: token-type + "Token" (eg. editToken, patrolToken, watchToken).
-               deferreds[ defaultOptions.ajax.url ][ key ] = $.Deferred()
+               promises[ defaultOptions.ajax.url ][ key ] = $.Deferred()
                        .resolve( value )
                        .promise( { abort: function () {} } );
        } );
                                        function ( code ) {
                                                if ( code === 'badtoken' ) {
                                                        // Clear from cache
-                                                       deferreds[ api.defaults.ajax.url ][ tokenType + 'Token' ] =
+                                                       promises[ api.defaults.ajax.url ][ tokenType + 'Token' ] =
                                                                params.token = undefined;
 
                                                        // Try again, once
                 */
                getToken: function ( type ) {
                        var apiPromise,
-                               deferredGroup = deferreds[ this.defaults.ajax.url ],
-                               d = deferredGroup && deferredGroup[ type + 'Token' ];
+                               promiseGroup = promises[ this.defaults.ajax.url ],
+                               d = promiseGroup && promiseGroup[ type + 'Token' ];
 
                        if ( !d ) {
-                               d = $.Deferred();
+                               apiPromise = this.get( { action: 'tokens', type: type } );
 
-                               apiPromise = this.get( { action: 'tokens', type: type } )
-                                       .done( function ( data ) {
+                               d = apiPromise
+                                       .then( function ( data ) {
                                                // If token type is not available for this user,
-                                               // key '...token' is missing or can contain Boolean false
+                                               // key '...token' is either missing or set to boolean false
                                                if ( data.tokens && data.tokens[type + 'token'] ) {
-                                                       d.resolve( data.tokens[type + 'token'] );
-                                               } else {
-                                                       d.reject( 'token-missing', data );
+                                                       return data.tokens[type + 'token'];
                                                }
-                                       } )
-                                       .fail( function ( code, result ) {
-                                               // Delete promise. Do not cache errors.
-                                               delete deferredGroup[ type + 'Token' ];
-                                               d.reject( code, result );
-                                       } );
 
-                               // Attach abort handler
-                               d.abort = apiPromise.abort;
+                                               return $.Deferred().reject( 'token-missing', data );
+                                       }, function () {
+                                               // Clear promise. Do not cache errors.
+                                               delete promiseGroup[ type + 'Token' ];
+
+                                               // Pass on to allow the caller to handle the error
+                                               return this;
+                                       } )
+                                       // Attach abort handler
+                                       .promise( { abort: apiPromise.abort } );
 
-                               // Store deferred now so that we can use this again even if it isn't ready yet
-                               if ( !deferredGroup ) {
-                                       deferredGroup = deferreds[ this.defaults.ajax.url ] = {};
+                               // Store deferred now so that we can use it again even if it isn't ready yet
+                               if ( !promiseGroup ) {
+                                       promiseGroup = promises[ this.defaults.ajax.url ] = {};
                                }
-                               deferredGroup[ type + 'Token' ] = d;
+                               promiseGroup[ type + 'Token' ] = d;
                        }
 
-                       return d.promise( { abort: d.abort } );
+                       return d;
                }
        };