недавно я пытаюсь снова заняться программированием после почти семилетнего перерыва. Что меня сейчас беспокоит, так это простой случай, когда функция становится «не» функцией при обратном вызове.
Вот где это происходит:
function xhrcall() {
let xhr = new XMLHttpRequest();
xhr.responseType = "json";
xhr.open("POST", "/api", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("token=xxxxxxx");
xhr.onload = () => {
let x = xhr.status == 200 ? xhr.response : false; //console.info(x) gives proper response
return x;
}
}
Когда я пытаюсь объявить его в переменной или использовать в качестве обратного вызова, мне выдается Uncaught Error.
Например, если я объявлю это так
let fn = xhrcall()
console.info(fn) //will gives me undefined result
window.callback = xhrcall()
callback() //will gives uncaught error not a function
Насколько я помню, все должно быть хорошо и работать, но это не так.
Это могут быть повторяющиеся вопросы, но я надеюсь, что кто-нибудь сможет объяснить, что здесь на самом деле не так. Я пропустил область действия функции? или это проблема с возвратом x?
Спасибо.
Если вы хотите передать или назначить функцию чему-то другому, чтобы ее использовать, вам нужно убрать (). Итак, let fn = xhrcall;
Этот вопрос похож на: Почему мой вызов функции, который должен быть запланирован с помощью setTimeout, выполняется немедленно?.
@Pointy, как вы сказали, let fn = xhrcall() должен присваивать любое возвращаемое значение переменной fn, но вместо этого я использовал console.info(fn) неопределенное значение, поэтому здесь чего-то не хватает.
Ваша функция xhrcall() ничего не возвращает. Обратный вызов onload что-то возвращает, но это не имеет ничего общего с тем, что возвращает xhrcall(). Оператор return работает только для функции, которая является его прямой содержащей функцией.
@Pointy Ах... теперь, когда вы указали на это, я только что понял, что return x находится за пределами области действия xhrcall(), неудивительно, что он не определен. Теперь я знаю, что делать. Спасибо.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


По умолчанию, если выполнение функции не заканчивается оператором return или если после ключевого слова return нет выражения, то значение return равно undefined.
xhrcall()returnс undefined[1]
Это значение присвоено fn, и ни глобальное свойство undefined, ни примитивное значение undefined не могут быть вызваны, поэтому ваши наблюдения последовательны.
Если вам нужно значение, которое функция стрелки, назначенная xhr.onload, будет return, вам придется найти другой способ получить это значение, поскольку функция стрелки не будет вызываться синхронно.
Вы можете получить это значение, используя EventTarget, которому Event будет отправлено, когда функция стрелки, назначенная xhr.onload, будет запущена и завершится. Event слушатели, слушающие это EventTarget, будут вызваны, когда это Event будет отправлено.
Например:
const xhrApiTarget = new EventTarget()xhr.onload = () => {
let x = xhr.status == 200 ? xhr.response : false
const apiResEvt = new Event("api-res")
apiResEvt.response = x
xhrApiTarget.dispatchEvent(apiResEvt)
}xhrApiTarget.addEventListener("api-res", (apiResEvt) => { apiResEvt.response })[1] Don’t confuse with the return in the arrow function assigned to xhr.onload.
Спасибо за ответ. Мне никогда не приходило в голову вызвать событие и вернуть значение через ответ на событие. Хотя я уже исправил свой код, используя параметр обратного вызова, я выберу здесь ваш ответ и поэкспериментирую с ним позже. Это интересно и воодушевляет меня. Спасибо.
let fn = xhrcall()означает «вызвать функцию с именемxhrcallи все, что она возвращает, присвоить это переменнойfn».