2017-03-12 7 views
0

私は、MediaWiki APIをクエリし、最初のクエリの結果ごとにもう一度クエリを実行し、コンソール上で「第2レベル」クエリの結果を表示する(動作する)Wikipediaユーザスクリプトを持っています(Firefox 52.0/Linuxの):いくつかの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クエリが完了したときに1つのコールバックを実行し、それらのすべての結果をアクセス/集約/結合したいとします。それはどうやってできますか?

+0

おそらく 'apprefix 'に'/'を追加することになります。 – Tgr

+0

これは、 "メイン"ユーザページ/ユーザトークページ、e。 g。 https://en.wikipedia.org/wiki/User_talk:Tim.landscheidt。 (このスクリプトの目的は「私」のユーザースペースのすべてのページを一覧表示することですが、普遍的なソリューションでは同じ「プレフィックス」を持つ他のユーザーを除外する必要がありますが、「Tim.landscheidt」では誤認はあまりありません。 - )。) –

答えて

0

すべてのクエリが完了するまで待つには、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!'); 
      }); 
     }); 
    }); 
}); 
+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はそれを処理しますが、決してチェックされません。いずれにしても、制限はWikiあたり500ページ(ローカル管理者の場合は5000)なので、おそらく良いはずです。)

関連する問題