2011-09-01 18 views
10

Tôi đang tự động tải mã (hàm) từ một máy chủ và thực thi nó dưới dạng mã javascript rồi lưu trữ nó trong một mảng và thực thi. Tất cả các đoạn mã này phải được thực thi chính xác một lần. Các psuedocode sau như vậyCó bất kỳ hoạt động javascript nguyên tử nào để xử lý bản chất không đồng bộ của Ajax không?

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

Vấn đề là bao la phức tạp hơn, nhưng về cơ bản nếu tôi thực hiện lệnh dưới đây

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

cả bốn sẽ thực hiện if (foo in fooArray) và cho rằng nó không phải là trong mảng, và cả bốn sẽ tiến hành lấy mã và thực thi nó. Tôi nhớ lại trong ngày học về các ẩn dụ và mutexes, có những thứ như vậy cho javascript.

+1

ràng nó là có thể, kể từ jQuery thực hiện điều này: http://stackoverflow.com/questions/7131991/asynchronous-and- đồng bộ điều khoản – Mchl

+0

Tôi đã viết một blog về nó [Tại sao không có công cụ đồng thời trong javascript] (http://uzairfarooq.github.io/why-no-concurrency-control-tool-in-javascript/) –

+1

liên kết là bị hỏng, phải là: http://blog.uzairfarooq.com/why-no-concurrency-control-tool-in-javascript –

Trả lời

30

JavaScript là ngôn ngữ tuyệt vời hoạt động tốt với các cuộc gọi lại không đồng bộ, thời gian chờ, khoảng thời gian và sự kiện của người dùng, nhưng không gặp phải bất kỳ sự cố đồng thời nào. Điều này là có thể bởi vì JavaScript về bản chất là một đoạn mã duy nhất được tạo luồng đơn luôn luôn được thực thi một cách nguyên tử và không bao giờ bị gián đoạn bởi một luồng khác đang chạy JavaScript.

Chức năng fetch() của bạn sẽ luôn được thực hiện mà không bị gián đoạn. Nếu nó được thực hiện như một phần của cuộc gọi lại AJAX và nếu nhiều cuộc gọi lại AJAX đang chờ xử lý, chúng sẽ được xếp hàng đợi.

Ví dụ khác: nếu bạn có trình xử lý sự kiện được gán cho phần tử đầu vào và bạn kích hoạt sự kiện nhiều lần cùng một lúc, trình xử lý sự kiện sẽ không được thực thi đồng thời. Thay vào đó, chúng sẽ được xếp hàng đợi và được thực hiện tuần tự. Điều này cũng áp dụng cho nhiều sự kiện được kích hoạt bởi setTimeout()/setInterval(). Là một lưu ý phụ: đây là một trong những lý do tại sao node.js rất mạnh mẽ: nó chỉ sử dụng một chuỗi và không bao giờ chặn trên I/O nhưng sử dụng gọi lại thay vào đó khi dữ liệu sẵn sàng/sự kiện xảy ra.

+5

Nói đúng [công nhân web] (http://en.wikipedia.org/wiki/Web_Workers) cho phép thực hiện đồng thời JS, nhưng vì sự tương tác duy nhất giữa các công nhân web và JS "bình thường" xảy ra thông qua các tin nhắn bạn * vẫn * không có bất kỳ vấn đề tương tranh nào. –

+0

Tomasz Tôi thấy những gì bạn đang nói, thanx. – puk

+0

@Tomasz, nếu cuộc gọi AJAX mất quá nhiều thời gian, có thể một người không muốn có quá nhiều (nhiều hơn 2 hoặc 6 tùy thuộc vào trình duyệt) đang chờ xử lý, vì vậy tôi cung cấp giải pháp bộ nhớ đệm bên dưới .. bạn nghĩ sao? –

1

Javascript cơ bản là một luồng, do đó bạn không cần một mutex. Bạn lấy có thể thiết lập cờ như vậy mà lấy cuộc gọi tiếp theo có thể tránh thực hiện cuộc gọi ajax ví dụ:

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; 
      }); 
     } 
    } 
} 
Các vấn đề liên quan