2017-03-12 4 views
0

MediaWiki API를 쿼리 한 다음 작동하는 첫 번째 쿼리의 결과 각각에 대해 다시 쿼리하여 콘솔에서 "두 번째 수준"쿼리의 결과를 인쇄하는 작은 (작동하는) Wikipedia 사용자 스크립트가 있습니다 (Firefox 52.0/리눅스) :여러 MediaWiki API 요청의 결과를 결합하는 방법은 무엇입니까?

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); 
       }); 
      }); 
     }); 
    }); 
}); 

지금 결합 대화 상자 개별 콘솔 출력을 대체 할 (일품 mw.loader.using('oojs-ui-windows').done(function() { OO.ui.alert('All results: ' + results); });).

즉, 모든 API 쿼리가 완료되면 하나의 콜백을 실행하여 모든 결과를 액세스/집계/결합합니다. 어떻게 할 수 있습니까?

+0

apprefix에'/'를 추가하고 싶을 것입니다. – Tgr

+0

"main"사용자 페이지/사용자 대화 페이지, 예를 들어 지. https://en.wikipedia.org/wiki/User_talk:Tim.landscheidt. (이 스크립트의 목적은 "내"사용자 공간에있는 모든 페이지를 나열하는 것이지만 범용 솔루션의 경우 동일한 "접두사"를 가진 다른 사용자를 제외해야하지만 "Tim.landscheidt"의 경우 오 탐지는 많지 않습니다. -).) –

답변

0

모든 쿼리가 완료 될 때까지 대기하려면 mediawiki.api.get()에 의해 반환 된 약속을 배열에 추가해야합니다 (예 :). 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!'); 
      }); 
     }); 
    }); 
}); 
+0

더 나은 솔루션, 특히 쿼리를 순차적으로 실행하는 솔루션은 환영합니다. 나는 아직이 대답을 받아들이지 않았다. 용어가 잘못되었거나 오해의 소지가 있거나 설명이 보편적이지 않은 경우에는 자신의 대답이나 의견을 추가하십시오. –

1

병렬 요청 (약속에 팀의 답변으로 같은, 조금 더 무거운) :

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!'); 
    }); 
}); 

당신이 병렬 처리 (당신이 여러 개의 계정이있는 경우 아마 좋은 생각)을 제한하려면 당신이 할 수있는 WR하려고 너무 복잡

.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)이므로