JavaScript同步选项

时间:2009-05-09 10:04:46

标签: javascript ajax caching synchronization

我想知道何时存在一个在JavaScript代码中执行同步的解决方案。例如,我有以下情况:我正在尝试从AJAX调用缓存一些响应值,问题是,它可以同时执行多次调用,因此它会导致代码中的竞争条件。所以我很好奇为此寻找解决方案?谁有想法要做?

6 个答案:

答案 0 :(得分:8)

我可以提供一个可能的解决方案,但是没有看到代码......不完全确定你在做什么,但没有理由不能这样做。

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!");
}

编辑:(重新:你的评论)

你正在寻找回调,就像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 );              
        };            
    });

答案 1 :(得分:6)

Javascript本质上是单线程的,至少对于普通的浏览器环境而言。永远不会有两个同时执行访问同一文档的脚本。 (新的Javascript工作线程在这里可能是一个例外,但它们根本不是为了访问文档,只是为了通过消息传递进行通信)。

答案 2 :(得分:4)

我找到了解决问题的方法。我不得不说它并不像我想要的那样完美,但到目前为止它的确有效,我认为这更像是暂时的解决方法。

$.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
        }
    }
})();

答案 3 :(得分:3)

是的,你可以让你的xmlHttpRequests同步,在非IE中使用bAsync参数在IE浏览器asynch option中将open do the same设置为false。

也许您可能想以某种方式链接您的请求。创建一个que堆栈,并在你向下走的路上发送请求。

答案 4 :(得分:3)

首先,重要的是要知道所有当前的JS实现都是单线程的,因此我们不讨论竞争条件并在通常使用的上下文中进行同步。

作为旁注,浏览器现在引入了工作线程,这将允许JS中的并发性,但目前情况并非如此。

无论如何,您仍然面临着期望通过异步调用收到哪些数据的问题,而您无法保证收到订单的顺序。

JS通过回调为您提供了一个非常好的解决方案。对于您将要发送的每个异步事件,将一个适当的回调函数附加到它,它将正确处理事件。按照你的意思,同步应该在那里发生。

答案 5 :(得分:1)

我知道这是后来的事,但我想我会改进。 Artem Barger制定了自己的解决方案,如果缓存的值为&#34;更新&#34; ...而只是将函数标记到一个链接队列中,对着缓存的值,这样你就有了一个对象,它保存了实际的缓存数据,以及在返回数据后用缓存数据调用的函数队列。

所以,如果它是&#34;更新&#34;只需将您的函数添加到与项目数据链接的队列中,并在数据返回时...设置数据然后迭代函数队列(回调)并使用返回的数据调用它们。

如果您想获得技术,可以在通过队列时设置特定的QOS超时,在迭代开始时设置秒表,如果到达特定时间,则调用setTimeout返回队列继续迭代...我希望你得到:) - 它基本上节省了一定数量的setTimout调用只需要一个。

查看上面的Artem Bargers代码,您应该了解我的建议。