recently I try to jump into coding again after stopping for almost 7 years long. What I'm troubled now is a simple case where function became "not" function on callback.
Here is where it happens:
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.log(x) gives proper response
return x;
}
}
When I try to declare it in variable or use it as callback it gives me Uncaught Error.
For example if I declare it like this
let fn = xhrcall()
console.log(fn) //will gives me undefined result
window.callback = xhrcall()
callback() //will gives uncaught error not a function
As I recalled, this should be fine and working yet it not.
This could be duplicate questions but I hope someone could explain what is actually wrong here. Did I miss the function scope? or is it the problem with return x?
Thank you.
By default, if a function's execution doesn't end at a return
statement, or if the return
keyword doesn't have an expression after it, then the return
value is undefined
.
xhrcall()
return
s undefined
[1]
This value is assigned to fn
and neither the global property undefined
nor the primitive value undefined
are invocable hence your observations are consistent.
If you need the value that the arrow function assigned to xhr.onload
will return
, you have to find a different way to collect that value since the arrow function will not be invoked synchronously.
You can collect that value using an EventTarget
that an Event
will be dispatched to when the arrow function assigned to xhr.onload
is fired and completes. Event
listeners listening to this EventTarget
will be invoked when this Event
is dispatched.
For example:
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
.