我有一个小的(工作)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查询的结果。怎么办?
答案 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!' );
} );
} );
} );
} );