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

Javascript 如何组合多个MediaWiki API请求的结果?,javascript,mediawiki-api,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',

我有一个小的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 );
                });
            } );
        } );
    } );
} );
现在,我想用一个组合对话框替换单个控制台输出,即使用“oojs ui windows”的la mw.loader.done函数{OO.ui.alert'All results:'+results;}


换句话说,我希望在完成所有API查询后执行一个回调,访问/聚合/组合所有API查询的结果。如何做到这一点?

要等待所有查询完成,需要将mediawiki.api.get返回的承诺添加到数组中,如下面的示例p所示。然后,jQuery提供了$.when方法,在解析了作为参数给出的所有承诺后执行回调。由于在本例中它们的数量是随机的,因此需要使用$.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!' );
            } );
        } );
    } );
} );

平行请求与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!' );
    } );
} );
如果您想限制并行性,如果您有许多帐户,那么您可以使用以下内容替换fire-the-requests块

.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可以处理它,从来没有检查过。在任何情况下,如果您是本地管理员,则每个wiki的页面限制为500页5000页,因此您可能会表现出色。

您可能希望在“apprefix”中附加/内容。这与主用户页面/用户对话页面不匹配,例如。G这个脚本的目的是列出我的用户空间中的所有页面;对于通用解决方案,我必须排除具有相同前缀的其他用户,但对于Tim.landscheidt,没有太多误报:-。更好的解决方案,特别是按顺序执行查询的解决方案,欢迎使用;因此,我还没有接受这个答案。如果术语错误、误导或解释不够普遍,请添加您自己的答案或评论。