Javascript 如何组合多个MediaWiki API请求的结果?
我有一个小的Wikipedia用户脚本,用于查询MediaWiki API,然后再次查询第一次查询的每个结果,并在Firefox 52.0/Linux控制台上打印第二级查询的结果: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',
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,没有太多误报:-。更好的解决方案,特别是按顺序执行查询的解决方案,欢迎使用;因此,我还没有接受这个答案。如果术语错误、误导或解释不够普遍,请添加您自己的答案或评论。