【问题标题】:Userscript to Loop over several HTTP Requests and combine the results?用户脚本循环多个 HTTP 请求并组合结果?
【发布时间】:2015-09-02 12:02:29
【问题描述】:

我现在知道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 循环中,该循环遍历不同的位置名称。
我的代码能够为职位显示单独的表格,但由于某种原因它们不按顺序排列。

我遇到的另一个问题是变量作用域。目前newStatTable 是在parseResponse 函数内部定义的,但我无法从函数外部访问它。我尝试从 var newStatTable 中删除 var 以使其成为全球性的,但它不起作用。

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

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

【问题讨论】:

  • 所以你的问题是 -- 他们不按顺序,对吗? -- 我假设你知道 httpRequests 是异步的,那么你为什么期望它们是有序的呢?
  • 当我说“不按顺序”时,我的意思是 WR 数组显示在 QB 数组之前。在for循环中,它不是按顺序进行的吗?另外,我更大的问题是我正在尝试找到一种方法来组合所有表,例如在我的示例数组输出中
  • 您的 for 循环按顺序进行,但“GM_xmlhttpRequest”创建了一个异步 AJAX 调用,这些完成发生在 for 循环完成之后,它们完成按照您调用的 HTTP 服务器决定完成它们的顺序 - 即按任何顺序。

标签: javascript greasemonkey tampermonkey mashup


【解决方案1】:

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

因此,对于多页混搭,您必须有某种方法来根据需要整理数据。 (在您的情况下,您可以整理团队名称。)

一般方法是:

  1. 创建an Associative Array 来保存数据。
  2. 在每个 AJAX 调用中传递一个 上下文
  3. 使用该上下文来控制 AJAX 回调函数如何解析数据并将其整理到整个数组中。
  4. 监控 AJAX 调用的状态,只有在它们全部完成后才进行最终处理。

这是它在用户脚本中的样子:

// ==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 奖金中分得一大笔钱,对吧? ;)

【讨论】:

  • 您对这个项目提供了巨大的帮助。我有one final question。为了回答你的问题,如果我赢了,我会给你一个削减:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-23
  • 1970-01-01
  • 2017-04-29
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多