2011-09-01 40 views
10

我動態地從服務器加載代碼(函數),並將其作爲javascript代碼執行,然後將其存儲在數組中並執行。所有這些代碼片段都必須執行一次。該僞代碼如下這樣是否有任何原子javascript操作來處理Ajax的異步性質?

function fetch(foo){ 
    if (foo in fooArray){ 
      //Do Nothing 
    else{ 
      //Fetch foo via Ajax and execute foo() 
    } 
} 

的問題是遠遠更爲複雜,但本質上,如果我發出以下命令

fetch('someFunctionName'); 
fetch('someFunctionName'); 
fetch('someFunctionName'); 
fetch('someFunctionName'); 

所有四個將執行if (foo in fooArray),並認爲它是不是數組中,所有四個將繼續獲取代碼並執行它。我記得當天學習信號量和互斥量,有沒有這樣的事情的JavaScript。

+1

Apparantly這是可能的,因爲jQuery的做到這一點:http://stackoverflow.com/questions/7131991/asynchronous-and-同步條款 – Mchl

+0

我寫了一個關於它的博客[爲什麼沒有在javascript中的併發工具](http://uzairfarooq.github.io/why-no-concurrency-control-tool-in-javascript/) –

+1

這個鏈接是破碎,應該是:http://blog.uzairfarooq.com/why-no-concurrency-control-tool-in-javascript –

回答

30

JavaScript是一種很好的語言,它在異步回調,超時,間隔和用戶事件方面效果很好,但沒有任何併發​​問題。這是可能的,因爲JavaScript本質上是單線程的 - 給定的代碼總是以原子方式執行,並且永遠不會被運行JavaScript的另一個線程中斷。

您的fetch()函數將始終執行而不會中斷。如果它作爲AJAX回調的一部分執行,並且多個AJAX回調未決,則它們將排隊。

另一個例子:如果您有一個事件處理程序分配給一個輸入元素,並且您一次多次觸發該事件,則事件處理程序將不會同時執行。相反,他們將排隊並按順序執行。這也適用於由setTimeout()/setInterval()觸發的多個事件。

作爲旁註:這是node.js如此強大的原因之一:它只使用單線程,從不阻塞I/O,但在數據就緒/事件發生時使用回調。

+5

嚴格地說[網絡工作者](http://en.wikipedia.org/wiki/Web_Workers)允許併發執行JS,但由於Web工作人員和「普通」JS之間的唯一交互是通過消息發生的,因此您仍然沒有任何併發​​問題。 –

+0

Tomasz我明白你在說什麼,thanx。 – puk

+0

@Tomasz,如果AJAX調用時間太長,也許人們可能不希望有太多(取決於瀏覽器的情況下有2或6個以上),所以我在下面提供了一個緩存解決方案。您怎麼看? –

1

Javascript本質上是單線程的,所以你不需要互斥鎖。你取可以設置標誌,使得後續獲取調用可能避免使Ajax調用,例如:

var beingFetched = {};//map onflight -> callbacks 
function fetch(foo){ 
    if (foo in fooArray){ 
     //Do Nothing 
    } else { 
     if (beingFetched.foo) { //note empty array is truthy 
      //register a callback 
      var callback = function(r){ 
      //anything you need to do wit the return object r 
      //maybe even eval it. 
      }; 
      //the callback would more likely be an argument to fetch itself 
      //or you could use a promise API instead so that you can at your will 
      //register multiple callbacks - for error, for success etc. 
      beingFetched.foo.push(callback); 
     } else { 
      beingFetched.foo = [];//truthy 
      //Fetch foo via Ajax and execute 
      $.ajax("getFoo/"+foo).done(function() { 
       _.each(beingFetched.foo, function(cb){ 
        cb.apply(cb,arguments); 
       }); 
       delete beingFetched.foo; 
      }); 
     } 
    } 
} 
相關問題