Так ваша главная ошибка, что если вам нужно сделать CORS запросы (или любые запросы AJAX, на самом деле), вам нужно для запуска кода с сервера (даже локального).
Google (и большинство браузеров) будет беспокоиться о вас, если протокол вашей страницы «file: ///», и вы пытаетесь загрузить вещи из Интернета (или наоборот). И «file: ///» также не может делать запросы для других файлов.
Дальнейшая ссылка: вы также не можете делать запросы «http» со страницы «https».
Это вторая проблема (та, которая была скрыта системой безопасности CORS), заключается в том, что ваши запросы AJAX запускаются параллельно прямо сейчас.
Для того, чтобы сделать эту работу так, как вы думаете, он должен (после первого возвращения, запустить второй), вам нужно будет:
- двигаться весь код в нижней части , относящийся к
xhr_2
внутри хода xhr.onload
- всего кода внутри
xhr.done
на дне внутри от xhr.onload
и заменить все дубликат информации (и использовать ссылки на возвращаемые результаты непосредственно)
Это приводит к чему-то вроде:
var search = document.getElementById('search');
search.addEventListener('click', function(){
var demo = document.getElementById('demo');
var player_name = document.getElementById('player_name').value;
var player_id;
// Interpolated API URLs
var name_url = 'https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/'+player_name+'?api_key=<THIS IS THE API KEY>';
var stats_url; //nested in the second ajax call to pass updated player_id
// Get player ID
var xhr = new XMLHttpRequest();
var id_return_text;
xhr.onload = function(){
if(xhr.status === 200) {
id_return_text = JSON.parse(xhr.responseText);
player_id = id_return_text[player_name].id;
demo.innerHTML = id_return_text[player_name].name +', your player ID is: '+player_id;
// Dropped the XHR_2 stuff here
var xhr_2 = new XMLHttpRequest();
var stats_return_text;
stats_url = "https://na.api.pvp.net/api/lol/na/v1.3/stats/by-summoner/"+player_id+"/summary?season=SEASON2016&api_key=<THIS IS THE API KEY>";
// CHANGED THIS TO BE XHR_2.onload -- IN HERE I KNOW XHR_1 IS ALREADY FINISHED
xhr_2.onload = function(){
if(xhr_2.status == 200) {
stats_return_text = JSON.parse(xhr_2.responseText);
demo.innerHTML += stats_return_text['playerStatsSummaries'].playerStatType;
}
};
xhr_2.open("GET",stats_url, true);
xhr_2.send();
}
};
xhr.open('GET', name_url, true);
xhr.send();
});
Это должно решить практически все ваши беды.
Смысл этого в том, что onload
является обратным вызовом, который увольняет долго после того, как программа была запущена, но xhr_2
сразу же после обжига вы запросили данные xhr_1
(не после того, как он возвращался данные).
Таким образом, player_id
не был определен.
Мы хотим подождать, пока мы не узнаем, что у нас есть player_id
, и мы знаем, что у нас есть это (или некоторая ошибка), когда мы находимся внутри обратного вызова до xhr_1.onload
.
Это становится ужасно запутанным и очень вложенным, и, хотя я думаю, что Promises и Async Functions/Generators - блестящие решения для управления этой сложностью, это выходит за рамки этого; так что вместо этого, я хотел бы предложить, глядя на какой-то функциональной композиции, чтобы упростить все это:
function noop() { } // do nothing
function getJSON (url, onload, onerror) {
var xhr = new XMLHttpRequest();
onload = onload || noop; // what I've been given or nothing
onerror = onerror || noop; // " "
xhr.onload = function() {
var data;
var error;
try {
// it's possible for parse to throw on malformed JSON
data = JSON.parse(xhr.responseText);
} catch (e) {
error = e;
}
return error ? onerror(error) : onload(data); // fire one or the other (don't fall into the handler, if onload throws)
};
xhr.onerror = onerror;
xhr.open("GET", url);
xhr.send();
}
// localize URL construction
function buildPlayerIdUrl (name) { return "https://______" + name + "_____"; }
function buildPlayerStatsUrl (id) { return "https://______" + id + "_____"; }
// gets player by name and runs a function after the player has been loaded
function getPlayer (player_name, done, error) {
var id_url = buildPlayerIdUrl(player_name);
function buildPlayer (response) {
var player = response[player_name];
return player;
}
function onload (response) {
done(buildPlayer(response));
}
// Load the JSON, build the player, pass the player to done()
getJSON(url, onload, error);
}
// get stats by player id and runs a function after the stats have been loaded
function getPlayerStats (player_id, done, error) {
var stats_url = buildPlayerStatsUrl(player_id);
function buildStats (response) {
var summary = response.playerStatsSummaries;
return summary;
}
function onload (response) {
done(buildStats(response));
}
// Load the JSON, build the stats, pass the stats to done()
getJSON(stats_url, onload, error);
}
// perform a search by player name
// note: All changes in step-number (1, 2, 3) are asynchronous,
// and thus, must be nested in callbacks of some sort
function search (player_name) {
// Step 1: load the player
getPlayer(playerName, function (player) {
// Step 2a: update the DOM with the player name/id
updatePlayerDom(player);
// Step 2b: load the player stats
getPlayerStats(player.id, function (stats) {
// Step 3: update the DOM with the stats
updateStatsDom(stats);
});
});
}
// player DOM update; keeping it nice and simple
function updatePlayerDom (player) {
document.querySelector(".Player-id").textContent = player.id;
document.querySelector(".Player-name").textContent = player.name;
}
// stats DOM update; same as above
function updateStatsDom (stats) {
document.querySelector(".Player-stats").textContent = stats.playerStatType;
}
// bootstrap yourself to your UI
some_button.onclick = function() {
var player_name = some_input.value;
search(player_name); // kick the whole thing off
};
Это определенно больше кода, но это также проще вносить изменения в каждой отдельной части, не наступая на пятки другой куски.
Это (надеюсь) также легче увидеть _eventual timeline_ всех частей, и как они текут, внутри самого search()
.
Ошибка должна быть достаточно ясной: 'https: URL.pre' не является допустимым URL-адресом, например,' https: // URL.pre', так что это, вероятно, просто опечатка. – adeneo
Я исправлю это. На самом деле это опечатка в моем вопросе. Я не опубликовал настоящий URL. – JoshuaT
Ошибка по-прежнему утверждает, что URL-адрес, который вы используете, не имеет действительного протокола * (для вызовов с перекрестным происхождением) *, поэтому с этим URL-адресом что-то не так, и вам будет сложно помочь, не зная * реальный * URL? – adeneo