Clarification when closing in Javascript using AJAX

I should have understood Cloures in Javascript correctly, but I obviously don’t ...

At the moment, the text I am reading has this function for an abstract AJAX call:

function request(url, callback){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = (function(myxhr){ return function(){ callback(myxhr); } })(xhr); xhr.open('GET', url, true); xhr.send(''); } 

Here is my real problem: my brain refuses to understand why this will not work:

 function request(url, callback){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = callback(xhr); xhr.open('GET', url, true); xhr.send(''); } 

I mean, in my opinion, what happens is that I call the request request ("http: // ...", a_callback). Inside request (), a new xhr object is created, and it is assigned to the callback ... will it not work? What are the (nasty) side effects? From my (limited) understanding, you need closures when, for example, in a loop, you can refer to the last value of a function variable. But here ... isn't it "var xhr = ..." every time a new object is created?

Please explain as if I had IQ 30 (which is probably true: D)

Merc.

+8
javascript closures ajax
source share
7 answers

In the first example, you do not need additional closure. This works fine:

 function request(url, callback){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ callback(xhr); }; xhr.open('GET', url, true); xhr.send(''); } 

In modern browsers (or browsers with polyfill fixes ) you can also do this:

 function request(url, callback){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = callback.bind(null, xhr); xhr.open('GET', url, true); xhr.send(''); } 

edit - also pay attention to @ Rainos answer. You do not need to pass an XHR object as a parameter.

change again - in response to a legitimate comment, you asked why your original idea would not work:

 function request(url, callback){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = callback(xhr); xhr.open('GET', url, true); xhr.send(''); } 

The problem with this line is here:

  xhr.onreadystatechange = callback(xhr); 

This sets the onreadystatechange value returned from the callback function call, then and there. In other words, instead of setting something to be called upon when the state changes, the call is made immediately. This error is really common, because it is easy to read incorrectly. However, at any time, JavaScript sees a link to a function, followed by a list of arguments in brackets, which is interpreted as a request to execute a function call, and not a request to wrap functions around a future function call.

+9
source share

When you write xhr.onreadystatechange = callback(xhr) , you call callback immediately and assign its result to onreadystatechange .

+6
source share

In the code you are showing, you are actually calling callback because of () at the end.

+1
source share
Good question. There is an important difference between calling a function and a pointer to a function - you want to give them a pointer to a function (this is not actually a closure, but what I call) so that they can call it later, This is really important if you ever either performed functional programming or played with anything in the Lisp family.
+1
source share

You do not need to pass xhr to the callback.

You can simply do xhr.onreadystatechange = callback;

and then use this to reference the xhr object inside the callback.

Example:

 xhr.onreadystatechange = function () { console.log(this.readystate); }; 

Disclaimer: For some cross browser support value> _>

+1
source share

In C and most other public languages, after returning a function, all local variables cease to be available, since the freeze frame is destroyed.

In JavaScript, if you declare a function inside another function, local variables can remain available after returning from the called function.

+1
source share

I answer my question because editing will confuse everything - please excuse me if this is not a way to do this.

So ... What I really wanted to write in my example:

 function request(url, callback){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ callback(xhr); } xhr.open('GET', url, true); xhr.send(''); } 

Or, since I don't need xhr (I can use "this"):

 function request(url, callback){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = callback; xhr.open('GET', url, true); xhr.send(''); } 

So, in the end, I was right ... using closure (as seen from the original question) is a complete waste of time, right?

It would be important if there was a loop, and I had to set up some callbacks. But in this case, since a new xhr is created each time a "request" is called, and it is set with the correct callback, there is no need to close it. Right?

Merc.

0
source share

All Articles