Параметры синхронизации JavaScript

Мне было интересно, когда существует решение для выполнения синхронизации в JavaScript-коде. Например, у меня есть следующий случай: я пытаюсь кэшировать некоторые значения ответа из вызова AJAX, проблема в том, что он может выполнять одновременно несколько вызовов, поэтому он приводит к состоянию гонки в коде. Так что мне очень любопытно найти решение для этого? У кого-нибудь есть идея, что делать?

Ответ 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, и вы должны получить суть того, что я предлагаю.