mediawiki.api: Use Promise.then instead of manual Deferred wrap
authorTimo Tijhof <krinklemail@gmail.com>
Wed, 5 Mar 2014 13:25:29 +0000 (14:25 +0100)
committerTimo Tijhof <krinklemail@gmail.com>
Sun, 16 Mar 2014 21:24:00 +0000 (22:24 +0100)
This is exactly what Promise.then is built for.

As a nice bonus, this way the fail/reject handler is transferred
automatically, and we don't need to call resolve() manually
since the return value from then(Function done) is the resolved
value (or another promise).

Minor clean up:

* category: Fix type documentation (primitive string instead of String object).
* category: Use simple boolean check to assert value is no longer false.
* Use String() cast instead of explicitly calling .toString.
* parse: Fix bug where in theory the deferred would never be resolved if
   the condition evaluated to false.
* watch: Add missing @static.
* watch: Simplify params/$.extend logic.

Change-Id: Iedbc70b2573c4f6b0d9e133c6f31e8f0b19c6f5e

resources/mediawiki.api/mediawiki.api.category.js
resources/mediawiki.api/mediawiki.api.edit.js
resources/mediawiki.api/mediawiki.api.js
resources/mediawiki.api/mediawiki.api.parse.js
resources/mediawiki.api/mediawiki.api.watch.js

index 57eda3d..026052c 100644 (file)
                 * @return {boolean} return.done.isCategory Whether the category exists.
                 */
                isCategory: function ( title, ok, err ) {
-                       var d = $.Deferred(),
-                               apiPromise;
+                       var apiPromise = this.get( {
+                               prop: 'categoryinfo',
+                               titles: String( title )
+                       } );
 
                        // Backwards compatibility (< MW 1.20)
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
-                               d.done( ok ).fail( err );
                        }
 
-                       apiPromise = this.get( {
-                                       prop: 'categoryinfo',
-                                       titles: title.toString()
-                               } )
-                               .done( function ( data ) {
+                       return apiPromise
+                               .then( function ( data ) {
                                        var exists = false;
                                        if ( data.query && data.query.pages ) {
                                                $.each( data.query.pages, function ( id, page ) {
                                                        }
                                                } );
                                        }
-                                       d.resolve( exists );
+                                       return exists;
                                } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
                },
 
                /**
                 * Get a list of categories that match a certain prefix.
-                *   e.g. given "Foo", return "Food", "Foolish people", "Foosball tables" ...
+                *
+                * E.g. given "Foo", return "Food", "Foolish people", "Foosball tables" ...
+                *
                 * @param {string} prefix Prefix to match.
                 * @param {Function} [ok] Success callback (deprecated)
                 * @param {Function} [err] Error callback (deprecated)
                 * @return {jQuery.Promise}
                 * @return {Function} return.done
-                * @return {String[]} return.done.categories Matched categories
+                * @return {string[]} return.done.categories Matched categories
                 */
                getCategoriesByPrefix: function ( prefix, ok, err ) {
-                       var d = $.Deferred(),
-                               apiPromise;
+                       // Fetch with allpages to only get categories that have a corresponding description page.
+                       var apiPromise = this.get( {
+                               list: 'allpages',
+                               apprefix: prefix,
+                               apnamespace: mw.config.get( 'wgNamespaceIds' ).category
+                       } );
 
                        // Backwards compatibility (< MW 1.20)
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
-                               d.done( ok ).fail( err );
                        }
 
-                       // Fetch with allpages to only get categories that have a corresponding description page.
-                       apiPromise = this.get( {
-                                       list: 'allpages',
-                                       apprefix: prefix,
-                                       apnamespace: mw.config.get( 'wgNamespaceIds' ).category
-                               } )
-                               .done( function ( data ) {
+                       return apiPromise
+                               .then( function ( data ) {
                                        var texts = [];
                                        if ( data.query && data.query.allpages ) {
                                                $.each( data.query.allpages, function ( i, category ) {
                                                        texts.push( new mw.Title( category.title ).getNameText() );
                                                } );
                                        }
-                                       d.resolve( texts );
+                                       return texts;
                                } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
                },
 
 
                 *  if title was not found.
                 */
                getCategories: function ( title, ok, err, async ) {
-                       var d = $.Deferred(),
-                               apiPromise;
+                       var apiPromise = this.get( {
+                               prop: 'categories',
+                               titles: String( title )
+                       }, {
+                               async: async === undefined ? true : async
+                       } );
 
                        // Backwards compatibility (< MW 1.20)
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
-                               d.done( ok ).fail( err );
                        }
 
-                       apiPromise = this.get( {
-                                       prop: 'categories',
-                                       titles: title.toString()
-                               }, {
-                                       async: async === undefined ? true : async
-                               } )
-                               .done( function ( data ) {
-                                       var ret = false;
+                       return apiPromise
+                               .then( function ( data ) {
+                                       var titles = false;
                                        if ( data.query && data.query.pages ) {
                                                $.each( data.query.pages, function ( id, page ) {
                                                        if ( page.categories ) {
-                                                               if ( typeof ret !== 'object' ) {
-                                                                       ret = [];
+                                                               if ( titles === false ) {
+                                                                       titles = [];
                                                                }
                                                                $.each( page.categories, function ( i, cat ) {
-                                                                       ret.push( new mw.Title( cat.title ) );
+                                                                       titles.push( new mw.Title( cat.title ) );
                                                                } );
                                                        }
                                                } );
                                        }
-                                       d.resolve( ret );
+                                       return titles;
                                } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
                }
 
        } );
index 91d9b8f..edfb34a 100644 (file)
@@ -60,7 +60,7 @@
                                action: 'edit',
                                section: 'new',
                                format: 'json',
-                               title: title.toString(),
+                               title: String( title ),
                                summary: header,
                                text: message
                        } ).done( ok ).fail( err );
index 7490862..914f3ec 100644 (file)
@@ -49,7 +49,7 @@
                        options = {};
                }
 
-               // Force toString if we got a mw.Uri object
+               // Force a string if we got a mw.Uri object
                if ( options.ajax && options.ajax.url !== undefined ) {
                        options.ajax.url = String( options.ajax.url );
                }
index 1c04b17..952dea4 100644 (file)
                 * @return {string} return.done.data Parsed HTML of `wikitext`.
                 */
                parse: function ( wikitext, ok, err ) {
-                       var d = $.Deferred(),
-                               apiPromise;
+                       var apiPromise = this.get( {
+                               action: 'parse',
+                               contentmodel: 'wikitext',
+                               text: wikitext
+                       } );
 
                        // Backwards compatibility (< MW 1.20)
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
-                               d.done( ok ).fail( err );
                        }
 
-                       apiPromise = this.get( {
-                                       action: 'parse',
-                                       contentmodel: 'wikitext',
-                                       text: wikitext
+                       return apiPromise
+                               .then( function ( data ) {
+                                       return data.parse.text['*'];
                                } )
-                               .done( function ( data ) {
-                                       if ( data.parse && data.parse.text && data.parse.text['*'] ) {
-                                               d.resolve( data.parse.text['*'] );
-                                       }
-                               } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
                }
        } );
 
index 653c90a..9d65e1f 100644 (file)
@@ -6,6 +6,7 @@
 
        /**
         * @private
+        * @static
         * @context mw.Api
         *
         * @param {string|mw.Title|string[]|mw.Title[]} pages Full page name or instance of mw.Title, or an
        function doWatchInternal( pages, ok, err, addParams ) {
                // XXX: Parameter addParams is undocumented because we inherit this
                // documentation in the public method..
-               var params, apiPromise,
-                       d = $.Deferred();
+               var apiPromise = this.post(
+                       $.extend(
+                               {
+                                       action: 'watch',
+                                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages ),
+                                       token: mw.user.tokens.get( 'watchToken' ),
+                                       uselang: mw.config.get( 'wgUserLanguage' )
+                               },
+                               addParams
+                       )
+               );
 
                // Backwards compatibility (< MW 1.20)
                if ( ok || err ) {
                        mw.track( 'mw.deprecate', 'api.cbParam' );
                        mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
-                       d.done( ok ).fail( err );
                }
 
-               params = {
-                       action: 'watch',
-                       token: mw.user.tokens.get( 'watchToken' ),
-                       uselang: mw.config.get( 'wgUserLanguage' ),
-                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages )
-               };
-
-               if ( addParams ) {
-                       $.extend( params, addParams );
-               }
-
-               apiPromise = this.post( params )
-                       .done( function ( data ) {
+               return apiPromise
+                       .then( function ( data ) {
                                // If a single page was given (not an array) respond with a single item as well.
-                               d.resolve( $.isArray( pages ) ? data.watch : data.watch[0] );
+                               return $.isArray( pages ) ? data.watch : data.watch[0];
                        } )
-                       .fail( d.reject );
-
-               return d.promise( { abort: apiPromise.abort } );
+                       .done( ok )
+                       .fail( err )
+                       .promise( { abort: apiPromise.abort } );
        }
 
        $.extend( mw.Api.prototype, {