Variables set in response of jQuery post request - javascript

I use the jQuery post requests a lot. I understand that when you are working within the response the variables have their own scope. Is there a good way to set variables in the response but have those variables available outside of the post? Like for other functions in JS.
Here is a sample of what I am doing:
$.post('URL', { }, function(data) {
var cData = $.parseJSON(data);
$.each(cData, function(k, v) {
var cID = v.id;
});
So what I do that I cannot access cID outside of the post request. Is there a way to make this work?
Any help would be great.
Thanks
UPDATE:
Here is a sample I just tested:
var savedCount;
$.post('/app/actions/countsAction.php', { call: "getCountFullByID", countID: countID}, function(data) {
savedCount = 1;
alert(savedCount);
});
alert(savedCount);
I get 2 alerts when I run this. The first one is a 1 when the alert is fired off in the $.post and the second one is undefined.

Just declare your variable outside of the $.post call:
var cID;
$.post('URL', function(data) {
var cData = $.parseJSON(data);
$.each(cData, function(k, v) {
cID = v.id;
});
});
...not sure what you're attempting to do with that though, as you're looping over a collection and continually (re)setting the value of a single variable. If you need to keep track of all the variables, consider holding the values in (maybe) an Array.
EDIT
If you need to do a synchronous ("blocking") $.post call, you can. From the docs for the asynch function parameter:
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
Cheers

You can store your whole data object instead of looping through and resetting the variable to a different value. Then you can access all your data outside. You should also define your variable outside of $.post so you have access to it
var cID;
$.post('URL', { }, function(data) {
cID = $.parseJSON(data);
});

Related

getJSON jQuery won't fill object

So I've got some code that retrieves a series of objects from an API. When I try to store them in a global variable, it doesn't seem to do anything. Here's the code:
var current_corpus = {};
function page_init() {
$.getJSON("http://resource1.com", function(data) {
populate_collections(data);
populate_citations(data);
});
}
function populate_collections(collections) {
$.each(collections, function (i, item) {
current_corpus[item] = [];
});
}
function populate_citations(collections) {
$.each(collections, function (index, collection) {
$.getJSON("http://resource2.com/" + collection.collection_id, function(data) {
current_corpus[collection] = data;
console.log(current_corpus);
});
});
}
When this finishes, current_corpus is completely empty. Logging these items verifies that they're being returned from the resources I'm posting to. I think there's just something about the asynchronous nature of these calls that I'm missing.
The line
current_corpus[item] = [];
is superfluous I think as the line
current_corpus[collection] = data;
should do the same thing while also tying data to the key object. Either way at the end of these functions running trying to access current_corpus via the console just gives me back an empty object.
Resources for dealing with AJAX stuff like this would be appreciated as well.
It all depends on what you want to do when the ajax requests complete. The A in ajax stands for Asynchronous meaning that such requests are non-blocking -- i.e. they will run in the background as control moves to the next line. Which explains why you're seeing an empty object right after the functions that invoke the ajax requests.
You can confirm that your code is working fine or you can do something once all the requests complete by using the following code snippet:
$(function() {
$(document).on('ajaxStop', function() {
console.log( current_corpus );
//do something with the now fully constructed object
});
});

jquery - scope getting lost in variable

I am developing application which will get some dynamic content which is irrelevant to my question. and the question is
var pat;
$.post('venki/path.jsp', { nam:nam } , function(data) {
pat=data;
alert(pat); //it will displayed the received code form path.jsp
});
alert(pat);// it will not keep the data received from path.jsp
Now I need to not lose the scope.
For example:
var pat=0;
$.post(
pat = 1
);
alert(pat);
It should alert 1 and not o
In java, i should use static. In jquery, how to declare static variables.
Got an answer:
Its simple and very useful and no need to worry about synchronous. the answer is tricky...
it is because post request is not completed when you are alerting pat value. To ensure that value is modified, alert it inside post success function:
var pat;
$.post('venki/path.jsp', { nam:nam } , function(data) {
pat=data;
alert(pat); //modified value
});
If i'm not mistaken, the $.post is async so the pat is not losing it's scope but executed before the pat=data executed
To make it synchronous call look at this question: how to make a jquery "$.post" request synchronous

How to access variable inside a block

I have an AJAX request:
var foo = [],
parse = '';
$.ajax({
type: "GET",
url: "some/path/",
data: somedata
}).done(function( data ){
$.each(data.item, function(i, value){
foo.push(value);
});
parse = foo.join(', ');
});
Now the string parse is the data that I want. How can I access that data? I tried showing it using alert(), but it's not displaying anything. I think this has to do with the variable scope.
How can I get that data?
parse looks like a global variable so it will be available anywhere. The issue is probably when you're trying to access it. You can ONLY access parse in your .done() handler or some function you call from that.
The reason for this is that your ajax call is asynchronous. That means that the operation starts, the rest of your javascript continues to execute and then SOMETIME LATER the ajax call completes and ONLY then is the parse variable valid. Because of this, there really is no reason to declare the parse variable the way you have. You should just use its value inside the .done() handler.
This is asynchronous programming and works differently than synchronous, sequential programming. You must use asynchronous programming techniques with asynchronous ajax calls.
If you try to access parse inside the .done() handler and it's still empty in there, then the issue is likely that data.item isn't what you think it is and maybe isn't triggering the .each() loop and thus nothing is getting put into foo or parse. To debug this case, you should look at what exactly is in data and data.item.
This would be my suggestion:
$.ajax({
type: "GET",
url: "some/path/",
data: somedata
}).done(function( data ){
// no reason for these variables to be wider scope than here
var foo = [], parse;
$.each(data.item, function(i, value){
foo.push(value);
});
parse = foo.join(', ');
// look at parse here
console.log(parse);
// if parse still empty, then look at data and data.item here
// to see what they are for debug reasons
console.log(data);
console.log(data.item);
// now, you can use parse here
callSomeFunction(parse);
});

Trigger a function only after the completion of multiple AJAX requests

I've got a particular function I want to run once, and only after the completion of several AJAX requests.
My current solution looks a bit like this:
function doWork() {
//This is the function to be run once after all the requests
}
//some tracking/counting variables
var ajaxDoneCounter = 0;
var numOfAjaxRequests = 5;
var workDone = false;
function doWorkTrigger() {
ajaxDoneCounter++;
if( !workDone && ajaxDoneCounter >= numOfAjaxRequests ) {
workDone = true;
doWork();
}
}
// ...
//and a number of ajax requests (some hidden within functions, etc)
//they look something like this:
$.ajax({
url: "http://www.example.com",
dataType: "json",
success: function( data ) {
//load data in to variables, etc
doWorkTrigger();
}
});
One obvious pitfall in the above is that any AJAX call that is not successful will not increment ajaxDoneCount and so doWork() will probably never be called. I can get around that using the error callback in inside any $.ajax, so that doesn't worry me too much.
What I want to know is whether the above is safe and/or good practice?
Is there a trick I've missed, or any thing else that might work better?
Update: Since jQuery 1.5, deferred objects [docs] provide a cleaner solution. Have a look at an example here.
I would use .ajaxComplete(), it will be triggered whenever an Ajax call completed (success or error):
var numOfAjaxRequests = 5;
$(document).ajaxComplete(function() {
numOfAjaxRequests--;
if(!numOfAjaxRequests) {
doWork();
}
});
Then you don't have to edit every Ajax request.
You could even use .ajaxSend() to get notified of starting Ajax requests, instead of hardcoding it (but I am not sure whether this really works, maybe you will experience race conditions):
var numOfAjaxRequests = 0;
$(document).ajaxSend(function() {
numOfAjaxRequests++;
});
I think you should use complete(XMLHttpRequest, textStatus) ajax event instead of success(data, textStatus, XMLHttpRequest).
According to jQuery help:
complete(XMLHttpRequest, textStatus)
A function to be called when the
request finishes (after success and
error callbacks are executed). The
function gets passed two arguments:
The XMLHttpRequest object and a string
describing the status of the request.
This is an Ajax Event.
I don't know enough about JavaScript internals, but there is a danger that the operation:
ajaxDoneCounter++;
is not atomic. If that is the case, then this could be subject to a race condition.

How to cache the result of $.post-request in jQuery?

I have a small jQuery script that gets information by looking at an ID.
What is the best way to prevent that the same data are requested more than once (e.g. what's the best practices for caching in jQuery)?
I have tried to use $.post and $.ajax with option "cache" set to true, but the request is being sent more than once.
Is it better to save collected data and use sets to see whether you'll have to request it or not?
Any ideas and suggestions are welcome!
If it matters, I use ASP.Net MVC on the server-side.
The cache option you saw on the documentation, refers to the browser's cache.
You can implement a pattern of self-memorizing functions in many ways, the goal is that the function result for determined argument (id in your case) is only computed once.
Since you are using an Ajax request, I would suggest you to use a callback argument also, e.g.:
var getInfo = (function () {
var cache = {}; // results will be cached in this object
return function (id, callback) {
if (cache[id] != null) { // if exist on cache
callback(cache[id]);
return;
}
// doesn't exists on cache, make Ajax request and cache it
$.post("info.url", { "id": id }, function (data) {
cache[id] = data; // store the returned data
callback(data);
});
};
})();
Example usage:
getInfo(5, function (data) {
alert(data);
});

Categories

Resources