如何组合几个MediaWiki API请求的结果?

时间:2017-03-12 07:30:40

标签: javascript mediawiki-api

我有一个小的(工作)Wikipedia用户脚本,用于查询MediaWiki API,然后再次查询第一个查询的每个结果,在控制台上打印“第二级”查询的结果(Firefox 52.0) / Linux)的:

mw.loader.using( [ 'mediawiki.api', 'mediawiki.ForeignApi' ] ).done( function () {
    var api = new mw.Api();
    api.get( {
        action: 'query',
        meta: 'globaluserinfo',
        guiprop: 'merged'
    } ).done( function ( data ) {
        data.query.globaluserinfo.merged.forEach( function( element, index, array ) {
            let url = element.url;
            var remoteapi = new mw.ForeignApi( url + '/w/api.php' );
            [mw.config.get('wgNamespaceIds').user, mw.config.get('wgNamespaceIds').user_talk].forEach( function( element, index, array ) {
                remoteapi.get( {
                    action: 'query',
                    list: 'allpages',
                    apprefix: data.query.globaluserinfo.name,
                    apnamespace: element
                } ).done( function (data2) {
                    for( var j = 0; j < data2.query.allpages.length; j++ )
                        console.log( url + '/wiki/' + data2.query.allpages[j].title );
                });
            } );
        } );
    } );
} );

我现在想用一个组合对话框(àlamw.loader.using( 'oojs-ui-windows' ).done( function () { OO.ui.alert( 'All results: ' + results ); } );)替换单个控制台输出。

换句话说,我想在完成所有API查询后执行一次回调,访问/聚合/组合所有API查询的结果。怎么办?

2 个答案:

答案 0 :(得分:1)

平行请求(与Tim的答案相同,对承诺的重视程度稍高):

mw.loader.using( [ 'mediawiki.api', 'mediawiki.ForeignApi' ] ).done( function () {
    // get all accounts of user
    new mw.Api().get( {
        action: 'query',
        meta: 'globaluserinfo',
        guiprop: 'merged',
        formatversion: 2,
        errorformat: 'wikitext',
        errorsuselocal: true
    } )
    // create a list of needed requests
    .then( function ( data ) {
        return data.query.globaluserinfo.merged.map( function( element, index, array ) {
            let url = element.url;
            let remoteapi = ( url === 'https:' + mw.config.get( 'wgServer' ) )
                ? new mw.Api()
                : new mw.ForeignApi( url + '/w/api.php' );                if (url === 'https:' + mw.config.get('wgServer'));
            let request = {
                action: 'query',
                generator: 'allpages',
                gapprefix: data.query.globaluserinfo.name + '/',
                gaplimit: 'max',
                prop: 'info',
                inprop: 'url'
            };
            return [
                $.extend( { namespace: mw.config.get('wgNamespaceIds').user }, request ),
                $.extend( { namespace: mw.config.get('wgNamespaceIds').user_talk }, request )
            ];
        } );
    } )
    // fire the requests and merge promises
    .then( function ( requests ) {
        var promises = requests.map( function ( request ) {
            return remoteapi.get( request ).then( function ( data ) {
                return $.map( data.query.pages, function( val, key ) {
                    return val.fullurl;
                } );
            } ), function () {
                console.log( 'FAIL = ' + JSON.stringify( arguments ) );
            } );
        } );
        promises.push( mw.loader.using( 'oojs-ui-windows' ) );
        return $.when.apply( $, promises ).then( function ( urls ) {
            // last result is from mw.loader, discard it
            urls.pop();
            return urls;
        } );
    } )
    // business logic
    .done( function ( urls ) {
        OO.ui.alert( 'All results: ' + urls.join( '\n' ) );
    } ).fail( function () {
        OO.ui.alert( 'FAIL!' );
    } );
} );

如果你想限制并行性(如果你有很多账户可能是个好主意)你可以替换&#34;触发请求&#34;阻止类似

.then( function ( requests ) {
    var status = Array( requests.length );
    let processNext = function () {
        let index = status.indexOf( undefined );
        if ( index >= 0 ) {
            status[index] = true;
            return remoteapi.get( requests[index] ).then( function ( data ) {
                requests[index] = $.map( data.query.pages, function( val, key ) {
                    return val.fullurl;
                } );
            } ), function () {
                console.log( 'FAIL = ' + JSON.stringify( arguments ) );
            } ).then( processNext, processNext );
        } else {
            return $.Deferred().resolve();
        }
    }
    let queue = Array( 5 ).map( function () {
        processNext();
    } ) );
    queue.push( mw.loader.using( 'oojs-ui-windows' ) );
    return $.when.apply( $, queue ).then( function () {
        return requests;
    } );
} )

(请注意,我没有做任何测试。此外,这不会处理延续,这对于尝试编写未经测试的代码来说太复杂。也许mw.Api会处理它,从不检查。无论如何。 ,每个维基的限制是500页(如果你是本地管理员,则为5000)所以你应该很好。)

答案 1 :(得分:0)

要等到所有查询都完成,mediawiki.api.get()返回的promise必须添加到数组中,在以下示例p中。然后jQuery提供$.when()方法,以便在作为参数给出的所有promise都已解析时执行回调。由于在这种情况下它们的数量是随机的,因此需要使用$.when.apply()

mw.loader.using( [ 'mediawiki.api', 'mediawiki.ForeignApi' ] ).done( function () {
    var api = new mw.Api();
    api.get( {
        action: 'query',
        meta: 'globaluserinfo',
        guiprop: 'merged'
    } ).done( function ( data ) {
        var p = [];
        var r = [];
        data.query.globaluserinfo.merged.forEach( function( element, index, array ) {
            let url = element.url;
            if (url === 'https:' + mw.config.get('wgServer'))
                var remoteapi = new mw.Api();
            else
                var remoteapi = new mw.ForeignApi( url + '/w/api.php' );
            [mw.config.get('wgNamespaceIds').user, mw.config.get('wgNamespaceIds').user_talk].forEach( function( element, index, array ) {
                p.push( remoteapi.get( {
                    action: 'query',
                    list: 'allpages',
                    apprefix: data.query.globaluserinfo.name + '/',
                    apnamespace: element
                } ).done( function (data2) {
                    for( var j = 0; j < data2.query.allpages.length; j++ )
                        r.push( url + '/wiki/' + data2.query.allpages[j].title );
                } ).fail( function () {
                    console.log( 'FAIL = ' + JSON.stringify( arguments ) );
                } ) );
            } );
        } );
        $.when.apply($, p).done( function () {
            mw.loader.using( 'oojs-ui-windows' ).done( function () {
                OO.ui.alert( 'All results: ' + r );
            } );
        } ).fail( function () {
            mw.loader.using( 'oojs-ui-windows' ).done( function () {
                OO.ui.alert( 'FAIL!' );
            } );
        } );
    } );
} );