Userscript循环遍历多个HTTP请求并合并结果?

时间:2015-09-01 17:56:32

标签: javascript greasemonkey tampermonkey mashup

我现在知道how to load columns, of a table, from an external webpage

现在我想扩展它并且:

  • 从多个页面获取表格数据(按玩家位置排名)。
  • 将其合并为一个主表。
脚本当前提取的

This is the URL (http:...fantasysports.yahoo.com...pos=QB)。列是团队名称和团队在各个职位的排名。

我想让它迭代其他位置(即WR,RB,TE)。这是通过将URL的最后2个字母更改为其各自的值来完成的。然后我希望将所有这些数据放在一个数组中,其中第一列是团队名称,第二列是QB位置的排名#,第三列是WR位置的排名#,依此类推。

我的计划是将GM_xmlhttpRequest置于for循环中,迭代不同的位置名称。
我的代码能够显示位置的单独表格,但由于某种原因它们不合适。

我遇到的另一个问题是变量范围。目前newStatTableparseResponse函数内定义,但我无法从函数外部访问它。我尝试从var移除var newStatTable以使其成为全局但不起作用。

这是我正在寻找的示例输出数组(注意:我只是随机选择了这些排名):

TeamName                QB   WR   TE    and so on...
---                     --   --   --
Jacksonville Jaguars    1    6    28
Sanfrancisco 49ers      4    2    32
Seattle Seahawks        31   5    10

这是我的尝试。

// ==UserScript==
// @name        _Grab stuff of a *static*, third-party web site.
// @include  http://football.fantasysports.yahoo.com/*
// @include  https://football.fantasysports.yahoo.com/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant       GM_xmlhttpRequest
// ==/UserScript==

pos = ["QB", "WR", "RB", "TE", "K", "DEF"];
for (x in pos) {
    GM_xmlhttpRequest ( {
        method:     "GET",
        url:        "http://football.fantasysports.yahoo.com/f1/326198/pointsagainst?pos=" + pos[x],
        onload:     parseResponse,
        onerror:    function (e) { console.error ('**** error ', e); },
        onabort:    function (e) { console.error ('**** abort ', e); },
        ontimeout:  function (e) { console.error ('**** timeout ', e); }
    } );
}
function parseResponse (response) {
    var parser  = new DOMParser ();
    var ajaxDoc         = parser.parseFromString (response.responseText, "text/html");
    var statRows        = ajaxDoc.querySelectorAll ("#statTable0 > tbody > tr");
    var newStatTable    = $(statRows).map ( function () {
        var tblRow      = $(this);
        var teamRank    = parseInt (tblRow.find (".rank-indicator").text().trim(), 10);
        var teamName    = tblRow.find ("td:eq(1)").text().trim().split(" vs")[0];

        return [ [teamName, teamRank] ]; //Return Teamname, Rank #
    } ).get ();

    console.log (newStatTable);
}

1 个答案:

答案 0 :(得分:3)

AJAX,由the very definition异步。这意味着返回的数据将以几乎任何顺序返回,并且除非您明确地将其复制出来,否则数据将不会在回调函数之外可用。

因此,对于多页面mashup,您必须有一些方法整理数据。 (在您的情况下,您可以整理团队名称。)

一般方法是:

  1. 创建an Associative Array以保存数据。
  2. 在每次AJAX调用中传递上下文
  3. 使用该上下文来控制AJAX回调函数如何解析数据并将其整理到整个数组中。
  4. 监控AJAX调用的状态,并在完成后才进行最终处理。
  5. 以下是用户脚本中的内容:

    // ==UserScript==
    // @name        _Mash up tables from several *static*, third-party, web pages.
    // @match       *://football.fantasysports.yahoo.com/*
    // @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
    // @grant       GM_xmlhttpRequest
    // ==/UserScript==
    const playerPositions   = ["QB", "WR", "RB", "TE", "K", "DEF"];
    const numPositions      = playerPositions.length;
    const baseURL           = "http://football.fantasysports.yahoo.com/f1/326198/pointsagainst?pos=";
    var rankingsTable       = {};  //-- This will be filled by the AJAX parser.
    var numPagesFetched     = 0;
    
    for (var J in playerPositions) {
        GM_xmlhttpRequest ( {
            method:     "GET",
            url:        baseURL + playerPositions[J],
            context:    playerPositions[J],
            onload:     parseResponse,
            onerror:    function (e) { console.error ('**** error ', e); },
            onabort:    function (e) { console.error ('**** abort ', e); },
            ontimeout:  function (e) { console.error ('**** timeout ', e); }
        } );
    }
    function parseResponse (response) {
        var playerPosition  = response.context;
        var parser          = new DOMParser ();
        var ajaxDoc         = parser.parseFromString (response.responseText, "text/html");
        var statRows        = ajaxDoc.querySelectorAll ("#statTable0 > tbody > tr");
        var newStatTable    = $(statRows).map ( function () {
            var tblRow          = $(this);
            var teamRank        = parseInt (tblRow.find (".rank-indicator").text().trim(), 10);
            var teamName        = tblRow.find ("td:eq(1)").text().trim().split(" vs")[0];
    
            return [ [teamName, teamRank] ];
        } ).get ();
    
        numPagesFetched++;
        console.log ('Fetched page ' + numPagesFetched + ' of ' + numPositions + '.');
    
        /*--- Now loop over the fetched rows and collate them into the master table, depending
              on playerPosition.
        */
        var columnIdx       = playerPositions.indexOf (playerPosition);
    
        for (var K in newStatTable) {
            var teamName        = newStatTable[K][0];
            var teamRank        = newStatTable[K][1];
            var teamStats       = rankingsTable[teamName]  ||  new Array (numPositions);
    
            teamStats[columnIdx]    = teamRank;
            rankingsTable[teamName] = teamStats;
        }
    
        if (numPagesFetched === numPositions) {
            displayFinalResult ();
        }
    }
    
    function displayFinalResult () {
        var sortedTeamNames = Object.keys (rankingsTable).sort ( function (zA, zB) {
            return zA.localeCompare (zB);
        } );
    
        const namePadStr    = new Array (25).join (' ');
        console.log (
            'Team                       Ranks QB, WR, RB, TE, K, DEF\n' +
            '------------------------   ------------------------------'
        );
        for (var J in sortedTeamNames) {
            var teamName    = sortedTeamNames[J];
            if (rankingsTable.hasOwnProperty (teamName) ) {
                console.log (
                    (teamName + namePadStr).slice (0, 24) + '  ', rankingsTable[teamName]
                );
            }
        }
    }
    

    我们将获得你的FF奖金的大幅削减,对吧? ;)