anonymous function variable scope [js, ajax] - javascript

$(".delete").click(
function() {
var thesender = this;
$(thesender).text("Del...");
$.getJSON("ajax.php", {},
function(data) {
if (data["result"])
$(thesender).remove(); // variable defined outside
else
alert('Error!');
}
);
return false;
}
);
This can cause problems if user clicks on another ".delete" before the ajax callback is called?

It will fire another ajax request at the same time doing the same thing. Whether that causes problems or not depends on the server side of things.
Typically you're deleting an id or key of some sort...I assume later in this code you will be, but for now it just issues another delete and call to ajax.php...what the result of this is entirely depends on that PHP page.
The callback happens for that ajax request when that ajax request finishes, each request in independent in this respect, so each callback is individually handled. thesender is inside your current closure, so it's unique as well for each request and it's respective callback.

Each time the click handler is called, a separate closure will be created, so each the AJAX callback will have a reference to the correct variable.
Therefore, you don't need to worry about it. (Assuming that the server can handle the requests)

It will fire another event. You could use one rather than click if you want the event to only fire once. Alternately, you can keep track as to whether an AJAX request is in progress; e.g by using data as follows:
$('.delete').click(function () {
if ($(this).data('inProgress')) {
// Request in progress; cancel?
return;
} else {
$(this).data('inProgress', true);
};
});
You could also achieve the same thing by using a global variable, adding classes, etc.

Related

Callback function for asynch request

The below code gets a state from latitude/longitude coordinates. How can I extract the value "result.body.region" from the scope of the anonymous function and use it in a higher scope?
latitude=tweets[0].latitude
longitude=tweets[0].longitude
var Request = unirest.get("https://montanaflynn-geocoder.p.mashape.com/reverse?latitude="+myobj.latitude+"&longitude="+myobj.longitude)
.header("X-Mashape-Key", "xxxxxxxxxxxxxxxxxxx")
.header("Accept", "application/json")
.end(function (result) {
state = result.body.region
});
What I want to do is write a callback function that will wait for the asynch request to finish and use that information in a different scope. I am self taught on javascript so I am struggling to understand callbacks. How can I do this?
The code you have already will do that.
You are probably trying to read the value of state before the callback has fired.
This is why we normally put the code to process the data in the callback: to make sure it runs after the asynchronous event has occurred.

Issue with multiple ajax calls simultaneously using jquery

I am using jquery for ajax calls
All the calls are called immmediately on page load and we are getting the responses at almost the same time.
the issue is, the 3 calls are fired and I am getting the data, but the callback function is fired for the first call only.
the other two callbacks are not called, the callback is defined as a separate function,
If I just write an alert instead of calling the callback method, all the 3 alert message are coming
So the issue is when we write the callback method, do any one have any idea of the strange behaviour?
We tried to reorder the calls, the behaviour is similar, which ever is called first, its callback will be called, for the rest, it will not be called
var url = "/test1";
ajaxCall(url, testMethod1, false);
var url = "test2";
ajaxCall(url, testMethod2, false);
var url = "test3";
ajaxCall(url, testMethod3, false);
testMethod1:function(data){
console.log("first"+data);
},
testMethod2:function(data){
console.log("second"+data);
},
testMethod3:function(data){
console.log("thrid"+data);
}
ajaxCall is defined as jquery ajax, the issue is only the testMethod1 is called, the rest 2 are not called
Regards
Hari
Well the thing that immediately caught my eye is that the URL for test1 has a forward slash preceding test1. This means that you are using a valid link in only test1. The alerts will trigger because you are probably not trying to access the data returned (which would still work even though the ajax request fails), where as you are trying to access the data in the coded call back functions you have provided, which will obviously throw a NullPointerException or whatever the equivalent as the ajax call fails due to an incorrect URL. Therefore data never gets set and the code doesn't work.

jQuery function execution order

I am having a problem, or perhaps a lack of understanding, with the jQuery execution order of $.get() function. I want to retrieve some information from a database server to use in the $.ready() function. As you all know, when the get returns, it passes the data to a return handler that does something with the data. In my case I want to assign some values to variables declared inside the ready handler function. But the problem is, the return handler of $.get() does not execute until after ready has exited. I was wondering if (a) am I doing this right/is there a better way or if (b) there was a way around this (that is, force the get return handler to execute immediately or some other fix I'm not aware of). I have a feeling this is some closure thing that I'm not getting about JavaScript.
As per request, I'll post an example of what I mean:
$(function() {
var userID;
$.get(uri, function(returnData) {
var parsedData = JSON.parse(returnData);
userID = parsedData.userID;
});
});
So as you can see, I'm declaring a variable in ready. Then using a get call to the database to retrieve the data needed. Then I parse the JSON that is returned and assign the userID to the variable declared before. I've tested it with a couple alerts. An alert after the get shows userID as undefined but then an alert in get's return handler shows it to be assigned.
$.get() is asynchronous. You have to use a callback to fill your variable and do the computation after the request is complete. Something like:
$(document).ready(function(){
$.get( "yourUrl", function( data, textStatus, jqXHR ) {
var myData = data; // data contains the response content
// perform your processing here...
registerHandlers( myData ); // you can only pass "data" off course...
});
});
// your function to register the handlers as you said you need to.
function registerHandlers( data ) {
// registering handlers...
}
$.get is an ajax request. A in AJAX stand for asynchronous, so script won't wait for this request to finish, but instead will proceed further with your code.
You can either use complete callback or you can use $.ajax and set async to false to perform synchronous request.
The $.get() function executes an async httprequest, so the callback function will be executed whenever this request returns something. You should handle this callback outside of $.ready()
Maybe if you explain exactly what do you want to do, it would be easier to help!
Are you looking for something like:
$(document).ready(function(){
var variable1, variable 2;
$.get('mydata.url', function(data){
variable1 = data.mydata1;
variable2 = data.mydata2;
});
});
If you declare the variables first, then you can set their values within the get call. You can add a function call at the end of the get handler to call a separate function using these values? Without some kind of example, its hard to go into any more detail.
Without seeing the full code, my guess is that you should declare your variable outside $.ready; initialize it in ready for the initial page load; then update it from the get callback handler.
for example
var x = ""; // declaration
$(document).ready(function() { x = "initial value"; });
$.get(...).success(function() { x = "updated from ajax"; });

Javascript call a function and do not call it again until it has returned

I have a button that when clicked calls a function - this function does some asynchronous Ajax and alerts a messagebox when the Ajax has returned. I do not want the user clicking on the button multiple times - if he clicks on the button when the Ajax has not returned then an error message should be alerted.
I know that this can be easily done using a global boolean variable (set it initally to true, make the ajax call and set it to false - set it again to true when the ajax returnes - check if the global is false when the user clicks the button). Also it can be done similarly if instead of the window/global object I use another global object containing the function and the boolean
However, I do not like very much the above methods - I think that they are a little old-school-Javascript. I was wondering if there was a more elegant way to do it, for instance using JS closures !
Using this method, your variable will not leak to the global scope. There's no way to manipulate this variable from outside the function:
var foo = (function(){
var pending = false;
return function foo(){
if(pending) return;
pending = true;
//...Code
//When finished:
pending = false;
}
})()
Others may suggest setting a property of the function, but this property can easily be adjusted from outside, which is not desirable.
var callback = (function()
{
var executing = false;
function yourfunc()
{
if(executing) return; // exit if pending
executing = true;
// here send the request
// edit: when the ajax response has returned
xxxx.onreadystatechange....{
// do what you need to do with ajax data
executing = false;
};
}
return yourfunc;
})();
callback();
Anonymous function has the form
(function(){}))()
The last () provides the parameters for the anonymous function.
In the above sample script ( by wes ) returns error as callback is not a defined function. Rob's method using closure sounds good.
Cheers.. Sree

Easy JS variable passing issue

I have an XHR call getting a date for me, but can't seem to pass it into the page. I just need to pass the date from the XHR call to a variable to be inserted via document.write.
Here is my code:
var upDated
function getUpdated(){
xmlhttp.open("HEAD", "MBP_box.JPG",true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
upDated = xmlhttp.getResponseHeader("Last-Modified");
alert(upDated);
}
}
xmlhttp.send(null)
}
and in the body....
document.write(upDated);
Instead of alert(upDated); you should have something like:
document.getElementById("some-element").innerHTML = upDated;
The idea is pretty simple, you must keep the logic inside the callback function (the one assigned to onreadystatechange) as you have no idea when it will be called (it will be called when the browser has received some response from the server, which may just as well not happen). So having some code after you set this connection won't work.
I'm not sure I understand what you want - do you mean you want the value of upDated, as returned via the Ajax call, to be inserted into the document body via document.write?
If so, you definitely can't do this. document.write is executed as soon as it is encountered, which will be while the document is loading. If you want to inject a value dynamically, you will have to use a DOM method.

Categories