【问题标题】:How to populate array with results from a series of async requests如何用一系列异步请求的结果填充数组
【发布时间】:2017-12-09 19:27:15
【问题描述】:

所以我试图获取两个数组 player_name 和 player_mmr 中的名称和分数。在 fillplayer 函数中同时调用 player_name[i] 和 player_mmr[i] 只会返回 undefined。我觉得我在这里遗漏了一些明显的东西,但我一生都无法弄清楚。我猜这与使用推送有关。

var btnmatch = document.querySelector('#get-data');
var btnchat = document.querySelector('#get-chat');
var matchid = document.querySelector('#match-id');
var tableheaders = [
    'Hero',
    'level',
    'Name',
    'Kills',
    'Deaths',
    'assists',
    'GPM',
    'XPM',
    'HD',
    'TD'
];

var dataheaders = [
    "hero_id",
    'level',
    'personaname',
    'kills',
    'deaths',
    'assists',
    'gold_per_min',
    'xp_per_min',
    'hero_damage',
    'tower_damage'
];

var playerids = [
    'player1',
    'player2',
    'player3',
    'player4',
    'player5',
    'player6',
    'player7',
    'player8',
    'player9',
    'player10'
];

var playeraccounts = [];
var requests = [];
var playersdata = [];
var player_name = [];
var player_mmr = [];

btnmatch.addEventListener('click', function () {
    GetMatchData(matchid.value);

});

btnchat.addEventListener('click', function () {
    for (i in playeraccounts) {
        requests[i] = new GetPlayerData(playeraccounts[i]);
    }
    console.log(player_name);
    console.log(typeof player_name);
    console.log(player_mmr);
    fillplayer();

});


function GetPlayerData(accountid) {
    var Url = 'https://api.opendota.com/api/players/' + accountid;
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", Url, true);
    xmlHttp.onreadystatechange = function ProcessRequestPlayer() {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
            if (xmlHttp.responseText == "Not found") {
                console.log("not found");
            } else {
                var info = xmlHttp.responseText;
                var playerjson = JSON.parse(info);

                player_name.push(playerjson.profile.personaname);
                if (playerjson.solo_competitive_rank === null) {
                    player_mmr.push(playerjson.mmr_estimate.estimate);
                } else {
                    player_mmr.push(playerjson.solo_competitive_rank);
                }
            }
        }
    };
    xmlHttp.send();
}

function GetMatchData(id) {
    var Url = 'https://api.opendota.com/api/matches/' + id;
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", Url, true);
    xmlHttp.onreadystatechange = function ProcessRequestMatch() {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
            if (xmlHttp.responseText == "Not found") {
                console.log("not found")
            } else {
                var info = xmlHttp.responseText;
                var testjson = JSON.parse(info);

                createTable2(testjson);
                getaccountids(testjson);

            }
        }
    };
    xmlHttp.send();
}

function getaccountids(json) {
    Object.keys(json.players).forEach(function (i) {
        playeraccounts.push(json.players[i].account_id);
    });
}

function fillplayer() {
    console.log(player_name);
    console.log(player_mmr);
    for (var i = 0; i < playerids.length; i++) {
        console.log(player_name[i]);

        document.getElementById(playerids[i]).getElementsByClassName('name')[0].innerHTML = player_name + ': ';
        document.getElementById(playerids[i]).getElementsByClassName('mmr')[0].innerHTML = player_mmr[i];
    }
}

function createTable2(json) {
    // Create table.

    var table = "<table class='game-table'>";
    table += "<thead>";
    table += "<tr>";
    for (var i = 0; i < 10; i++) {
        table += "<th>" + tableheaders[i] + "</th>";

    }
    table += "</tr>";
    table += "</thead>";
    table += "<tbody>";

    for (var i = 0; i < 5; i++) {
        table += "<tr class='radiant'>";
        for (var x = 0; x < dataheaders.length; x++) {
            table += "<td>" + json.players[i][dataheaders[x]] + "</td>";
        }
        table += "</tr>";
    }

    for (var i = 5; i < 10; i++) {
        table += "<tr class='dire'>";
        for (var x = 0; x < dataheaders.length; x++) {
            table += "<td>" + json.players[i][dataheaders[x]] + "</td>";
        }
        table += "</tr>";
    }
    table += "</tbody>";
    table += "</table>";
    var sectie = document.getElementById('table');
    if (json.radiant_win == false) {
        var winnertekst = document.createTextNode('Dire Victory');
    } else {
        var winnertekst = document.createTextNode('Radiant Victory');
    }

    console.log(table);
    console.log(typeof table);
    console.log(sectie);
    document.getElementsByClassName('winnersect')[0].appendChild(winnertekst);
    sectie.innerHTML = table;
}

【问题讨论】:

  • 问题是 player_nameplayer_nmr 填充在异步请求的 回调 中,并且没有或不是所有从 GetPlayerData 发送的请求都会按时完成fillplayer 被调用。异步请求何时以何种顺序完成是不可预测的。您需要确保在 last 回调完成后调用fillplayer。使用承诺。

标签: javascript arrays asynchronous promise xmlhttprequest


【解决方案1】:

正如 marekful 所说,您可以使用 Promise,也可以查看 Async Functions 如果您没有将 IE 定位为浏览器,则可以使用 Fetch API 而不是 XMLHttpRequest 并具有更清晰的结构。这两个都返回一个你可以消费的承诺。 另一个显示如何组合 fetch 和 async 函数的来源 JavaScript Fetch API and using Async/Await .

【讨论】:

    猜你喜欢
    • 2021-09-11
    • 1970-01-01
    • 2023-03-21
    • 2013-03-09
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多