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?
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
}
}
})();
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 );
};
});
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).
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
}
}
})();
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.
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.
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.
© 2022 - 2024 — McMap. All rights reserved.