Мне было интересно, когда существует решение для выполнения синхронизации в JavaScript-коде. Например, у меня есть следующий случай: я пытаюсь кэшировать некоторые значения ответа из вызова AJAX, проблема в том, что он может выполнять одновременно несколько вызовов, поэтому он приводит к состоянию гонки в коде. Так что мне очень любопытно найти решение для этого? У кого-нибудь есть идея, что делать?
Параметры синхронизации JavaScript
Ответ 1
Я нашел решение для своей проблемы. Я должен сказать, что это не так идеально, как я искал, но до сих пор это работает, и я думаю об этом больше, как о временной работе.
$.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
}
}
})();
Ответ 2
Я могу предложить возможное решение, но не видя кода... не совсем уверен, что вы делаете, но нет причин, по которым вы не могли этого сделать.
Базовый код в jQuery: (не проверен и сокращен... но я сделал что-то подобное)
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: ваш комментарий)
Вы ищете обратные вызовы, так же, как это сделает jQuery.
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 );
};
});
Ответ 3
Javascript по сути является однопоточным, по крайней мере, для обычной среды браузера. Не будет двух одновременных исполнений скриптов, обращающихся к одному и тому же документу. (новые рабочие потоки Javascript могут быть исключением здесь, но они не предназначены для доступа к документам вообще, просто для связи путем передачи сообщений).
Ответ 4
Да, вы можете сделать синхронный xmlHttpRequests, в не-IE установите параметр asynch в значение false в методе open, в браузерах IE сделать то же с параметром bAsync.
Возможно, вам захочется как-то связать ваши запросы. Создайте стек очереди и отправьте запросы по мере того, как вы продвигаетесь по очереди.
Ответ 5
Во-первых, важно знать, что все текущие реализации JS являются однопоточными, поэтому мы не обсуждаем условия гонки и синхронизацию в контексте, который обычно используется.
В качестве дополнительной заметки браузеры теперь вводят рабочие потоки, которые позволят concurrency в JS, но пока это не так.
Во всяком случае, вы все еще сталкиваетесь с проблемами с тем, какие данные вы ожидаете получить обратно асинхронными вызовами, и у вас нет гарантий относительно того, как вы будете получать какие-то вещи.
JS дает вам очень хорошее решение с обратными вызовами. Для каждого асинхронного события, которое вы будете отправлять, присоедините к нему надлежащую функцию обратного вызова, которая будет обрабатывать событие должным образом. Синхронизация, как вы это понимаете, должна происходить там.
Ответ 6
Я знаю, что это путь, но я думал, что просто улучшу. Артем Баргер разработал свое собственное решение, которое использует setTimeout, если кешированное значение "обновляется"... Вместо этого просто помечайте функцию в связанной очереди по кешированному значению, чтобы у вас был объект, который содержит фактические кэшированные данные и очередь функций для вызова с кэшированными данными после возвращения данных.
Итак, если это "обновление", просто добавьте свою функцию в очередь, связанную с данными элемента, и когда данные вернутся... установите данные, а затем перейдете в очередь функций (обратных вызовов) и вызовите их с возвращенными данными.
Если вы хотите получить техническую информацию, вы можете установить определенный тайм-аут QOS при прохождении очереди, установить секундомер в начале итерации, и если вы достигнете определенного времени, тогда вызовите setTimeout, чтобы вернуться в очередь для продолжения итерации... Надеюсь, вы получили это:) - Это в основном экономит X количество звонков setTimout, требуется только один.
Просмотрите приведенный выше код Artem Bargers, и вы должны получить суть того, что я предлагаю.