Я пытаюсь вызвать функцию JavaScript, но не могу получить к ней доступ, так как, по-видимому, она не определена - PullRequest
0 голосов
/ 20 января 2020

Я пытаюсь вызвать функцию JavaScript (apiCall), используя прослушиватель событий, связанный с выпадающим списком, прослушивающим изменения.

Я хочу, чтобы функция была перезапущена, когда из раскрывающегося списка выбран другой элемент меню, но когда я запускаю этот код, в приемнике событий возникает ошибка, говорящая о том, что «apiCall» не определен хотя это явно прямо над.

Есть предложения?

Заранее спасибо.

// API CALL 
var request = new XMLHttpRequest()
request.open('GET', base + forecast + key + city, true)

request.onload = function apiCall() {
  var data = JSON.parse(this.response)
  console.log(data)
  string = JSON.stringify(data, null, 4);
  app.innerHTML = string;
}


document.getElementById("locationList").addEventListener("change", apiCall)


//send request
request.send()

Ответы [ 2 ]

2 голосов
/ 20 января 2020

Функция, которую вы назначаете window.onload, - это функция выражение , а не функция объявление . Имя именованного выражения функции не добавляется в окружающую область, и поэтому оно доступно только локально для самого выражения функции. Это означает, что вы не сможете ссылаться на него позже вне функции:

function iAmAFunctionDeclaration() {
  console.log("abc");
}

+function iAmAFunctionExpression() {
  console.log("abc");
}

console.log(typeof iAmAFunctionDeclaration);
console.log(typeof iAmAFunctionExpression); // undefined (not added to the `window`).

Вместо этого, если вы можете сделать apiCall объявлением функции, вы сможете получить доступ к ее имени, чтобы выполнить его позже, а также назначить его как обратный вызов:

function apiCall() {
  console.log("performing api call");
}

window.onload = apiCall;
document.addEventListener("click", apiCall);

Чтобы ваш API-вызов работал правильно, вы можете либо .bind() ваш request к вашей apiCall функции, как показано @ Stratubas или вы можете заменить ключевое слово this на request. Это позволит вам обрабатывать то, на что ссылается this в вашем обратном вызове. Чтобы узнать больше о this внутри обратного вызова, см. этот ответ и этот ответ .

Подробнее о выражениях функций можно прочитать здесь.

1 голос
/ 20 января 2020

Сначала пишется функция, а затем назначается request.onload:

var request = {};

function apiCall() {
  console.log('hello');
}

request.onload = apiCall;

request.onload();
apiCall();

Таким образом, ваш код должен выглядеть так:

// API CALL 
var request = new XMLHttpRequest()
request.open('GET', base + forecast + key + city, true)

function apiCall() { // <- removed 'request.onload' from here...
  var data = JSON.parse(this.response)
  console.log(data)
  string = JSON.stringify(data, null, 4);
  app.innerHTML = string;
}

request.onload = apiCall; // <- and placed it here

const boundApiCall = apiCall.bind(request); // to keep your 'this' object

document.getElementById("locationList").addEventListener("change", boundApiCall)


//send request
request.send()

Редактировать: Я вижу, что вы используете this внутри своей функции. Я не уверен на 100% (все еще учусь здесь), но я думаю, что дополнительный bind, который я добавил, сохранит вашу this, работающую как прежде.

...