I was wondering whenever exists a solution to perform synchronization in JavaScript code. For example I have the following case: I'm trying to cache some response values from AJAX call, the problem is, that it's possible to perform simultaneously several calls, therefore it leads to race condition in the code. So I'm very curious to find solution for that? Any one has idea that to do?
6 Answers
I can offer a possible solution, but without seeing the code ... not completely sure what you are doing, but there is no reason why you couldn't do this.
Basic code in jQuery : (not tested and abbreviated ... but I have done things similar)
var needAllThese = {};
$(function(){
$.ajax("POST","/somepage.aspx",function(data) {
needAllThese.A = "VALUE";
});
$.ajax("POST","/somepage2.aspx",function(data) {
needAllThese.B = "VALUE";
});
$.ajax("POST","/somepage3.aspx",function(data) {
needAllThese.C = "VALUE";
});
startWatching();
});
function startWatching() {
if (!haveEverythingNeeded()) {
setTimeout(startWatching,100);
return;
}
everythingIsLoaded();
}
function haveEverythingNeeded() {
return needAllThese.A && needAllThese.B && needAllThese.C;
}
function everythingIsLoaded() {
alert("Everything is loaded!");
}
EDIT: (re: your comment)
You're looking for callbacks, the same way jQuery would do it.
var cache = {};
function getSomeValue(key, callback) {
if (cache[key]) callback( cache[key] );
$.post( "url", function(data) {
setSomeValue(key,data);
callback( cache[key] );
});
}
function setSomeValue(key,val) {
cache[key] = val;
}
$(function(){
// not sure you would need this, given the code above
for ( var i = 0; i < some_length; ++i) {
$.post( "url", function(data){
setSomeValue("somekey",data);
});
}
getSomeValue("somekey",function(val){
$("#element").txt( val );
};
});

- 44,326
- 9
- 65
- 80
-
code looks like this: $(function(){ for ( var i = 0; i < some_length; ++i) $.post( "url", function(data) { setUpSomeValue( data); }); var setUpSomeValue = (function() { var cache = {} return function( data) { if (!cache[data]) $.post(.....) //update cache with new data else return cache[data]; } })(); So whenever two similar data is returned I'm still doing the second AJAX call, because I'm unable to notify about cache update. So that's why I'm think about making some synchronization there. – Artem Barger May 09 '09 at 12:00
-
To be honest I'm not sure I understand how you last solution will help me in my problem. Do you mind to explain a little? – Artem Barger May 09 '09 at 13:10
-
It does exactly what you asked. Using callbacks ... and if you wrote the example code in your comment, you're using callbacks in your .$post call, it's the same concept ... you should have no problem understanding it unless you didn't write the code you're having trouble with – Chad Grant May 09 '09 at 14:01
-
So let say, some_length = 2 consequently it will produce two $.post() calls. And let say say both will return the same date. Now the second call takes a lot of time to response so the first call for setSomeValue will produce another $.post(), meanwhile the value is not updated, so the second call will be sure that there is no value in the cache and will call second time the unnecessary code. So I still don't see how your solution solves this case. – Artem Barger May 09 '09 at 17:31
-
I pointed out the unnecessary code. I would consider redesigning your app/data if you are having this many issues. I have not met a race condition like you talking about and I've been coding jQuery / JSON services every day for 2 years. Maybe you should get all the dates in one call .. who knows. Like I said, no code and I am just guessing at your problem – Chad Grant May 09 '09 at 22:52
-
I don't have that many issues, actually only one. I'm trying to optimize and perform as less calls as I could to server and trying to do the calls itself as lighter as it could be. Anyway your solution has same BUG/issue and it's really weird you don't see. The calls is asynchronous so they are independent, so then I call twice for setSomeValue with same key value, the first one will proceed $.post therefore will be waiting for result and cache will not be updated, so the second one, instead of waiting will perform second unnecessary code. Correct me if I'm wrong. – Artem Barger May 10 '09 at 06:18
Javascript is inherently single-threaded, at least for the normal browser environment. There will never two simultaneous executions of scripts accessing the same document. (the new Javascript worker threads might be an exception here, but they're not meant to access documents at all, just to communicate by message passing).

- 5,391
- 1
- 18
- 17
-
2Javascript may be single threaded but you can have race conditions, there's no guarantee of the order in which asynchronous requests are made, when they complete, etc. This is especially true with firefox-add ons and multiple windows. – Bjorn May 09 '09 at 10:40
-
1you obviously need to write code that can handle the problems you describe. This is not the same kind of synchronization you need in other languages to prevent threads from interfering with each other by reading incomplete results from memory or overwriting each others changes in between larger operations. There is only one active stream of javascript execution in the browser environment. all event handlers are called in a serialized fashion one after another. – fforw May 09 '09 at 11:13
-
1Just try to write for instance one AJAX call, then in the handler call another AJAX request, and in the second handler access some global variable. And now make a several iterations of the first call. Are still sure there is a serialized access to that variable? Could you predict the order? And one more thing if I was able to write working code for problem I've described I would never ask here for help. – Artem Barger May 09 '09 at 11:51
-
1The order is not predictable, but all responses are going to be handled serialized way, one after another. One response wins the race and the response handler gets called. if another response comes in while the first response handler is still running, the second response handler will have to wait until the first one exits. – fforw May 09 '09 at 12:32
-
Once responses have to race, there is an access violation in global variable access. In my case I clearly can see that handlers were called simultaneously and while first updating variable, second cannot see it and therefore perform unnecessary heavy computation again. – Artem Barger May 09 '09 at 12:44
I have found solution for my problem. I have to say it's not that perfect as I was looking for, but so far it works and I think about that more as temporarily work around.
$.post( "url1", function( data)
{
// do some computation on data and then
setSomeValue( data);
});
var setSomeValue = ( function()
{
var cache = {};
return function( data)
{
if ( cache[data] == "updating")
{
setTimeout( function(){ setSomeValue( data);}, 100);
return;
}
if ( !cache[date])
{
cache[date] = updating;
$.post( "url2", function( another_data)
{
//make heavy computation on another_data
cache[data] = value;
// update the UI with value
});
}
else
{
//update the UI using cached value
}
}
})();

- 40,769
- 9
- 59
- 81
-
Thanks for this. I'm surprised how many said "it's single threaded so it's not a problem" which is totally incorrect in a world with asynchronous callbacks. You described the problem nicely and this is a perfectly effective approach for me. – Stuart Watt Jan 08 '15 at 15:20
Yes you can make your xmlHttpRequests synchronous, in non-IE set the asynch option to false on the open method, in IE browsers do the same with the bAsync parameter.
Maybe you might want to chain your requests somehow. Create a que stack and send the requests as you make your way down the que.

- 69,215
- 39
- 136
- 164
-
1synchronous requests are bad because they prevent all other javascript event handlers from being executed. – fforw May 09 '09 at 11:07
-
I just answered his question, I didn't attempt to judge his need. Downvote that? heh. – Bjorn May 09 '09 at 11:28
-
People may want synchronization for many different reasons, for example you want a request to be processed before handling any more user input. There are other reasons. Etc. – Bjorn May 09 '09 at 11:39
First, it's important to know that all current JS implementations are single-threaded, therefore we are not discussing race-conditions and synchronizing in the context it is usually used.
As a side note, browsers are now introducing worker threads which will allow concurrency in JS, but for now this is not the case.
Anyway, you still are facing issues with what data you are expecting to receive back form asynchronous calls and you have no guarantee as to the order you will receive things.
JS gives you a very nice solution to this with callbacks. For each asynchronous event you will be sending, attach a proper callback function to it, which will handle the event properly. Synchronization, in the way you mean it, should be happening there.

- 161,610
- 92
- 305
- 395
-
Ok, I my case I' trying to build the cache for some responses from server. There is a AJAX call, which does have it's own handler, but in the handler there is a call for function, which accessing the cache variable and if variable is set use it overwise make another heavy AJAX call. So if I'm using asynchronous call, I probably could miss the update of cache and perform unnecessary call twice, this behavior is unwilling, so I was thinking of the way I could synchronize the access for reading/writing of that variable. – Artem Barger May 09 '09 at 11:45
I know it is way after but thought I would just give an improvement. Artem Barger worked out his own solution which uses setTimeout if the cached value is "updating" ... Instead just tag the function onto a linked queue against the cached value so you have an object which holds the actual cached data and the queue of functions to call with the cached data once the data is returned.
So, if it is "updating" just add your function to the queue which is linked against the item data and when the data returns...set the data and then iterate over the queue of functions (callbacks) and call them with the returned data.
if you wanted to get technical you could set a specific QOS timeout as you go through the queue, set a stop watch at the beginning of the iteration and if you reach a specific time then call a setTimeout to go back into the queue to continue the iteration...I hope you got that :) - It basically saves X amount of setTimout calls one only one is needed.
View Artem Bargers code above and you should get the gist of what I propose.

- 11
- 1