2009-02-17 30 views
43

Có một thứ như là một thử nghiệm và thiết lập nguyên tử, semaphore hoặc khóa trong Javascript không?Javascript semaphore/test-and-set/lock?

Tôi có javascript gọi quy trình nền không đồng bộ qua giao thức tùy chỉnh (quá trình nền thực sự chạy trong một quy trình riêng biệt, không liên quan đến trình duyệt). Tôi tin rằng tôi đang chạy vào một điều kiện chủng tộc; quá trình nền trả về giữa thử nghiệm của tôi và bộ của tôi, vặn vẹo mọi thứ ở phía bên javascript. Tôi cần một hoạt động thử nghiệm và thiết lập để biến nó trở thành một semaphore thực sự.

Dưới đây là các mã javascript mà cố gắng để phát hiện các tiến trình nền và xếp hàng họ lên:

Call = function() { 

var isRunning = true, 
    queue = []; 

return { 
    // myPublicProperty: "something", 

    call: function (method) { 
      if (isRunning) { 
       console.log("Busy, pushing " + method); 
       queue.push(method); 
      } else { 
       isRunning = true; 
       objccall(method); 
      } 
     }, 

     done: function() { 
      isRunning = false; 
      if (queue.length > 0) { 
       Call.call(queue.shift()); 
      } 
     } 
    }; 
}(); 

Gọi là một singleton mà thực hiện các hàng đợi; bất cứ ai muốn gọi một quá trình bên ngoài không Call.call ("cái gì").

Bất kỳ ý tưởng nào?

+0

Bạn có thể muốn chỉ định 'quy trình' của bạn chi tiết hơn. Đây có phải là javascript phía máy chủ không? –

+2

Mã Javascript luôn là nguyên tử, vì vậy không cần phải khóa hoặc bất cứ thứ gì. Xem [Tại sao chúng ta không có công cụ kiểm soát tương tranh trong javascript?] (Http://uzairfarooq.github.io/why-no-concurrency-control-tool-in-javascript/). –

Trả lời

2

Có lẽ bạn có thể thực hiện một số nguyên semaphore cơ bản, chỉ cần thêm biến vào DOM và khóa/mở khóa nó và đảm bảo chức năng của mình liên tục kiểm tra nó, nếu không thời gian chờ họ =)

Nếu bạn đang sử dụng một khuôn khổ như vậy như Mootools bạn có thể thử xử lý luồng ứng dụng với các sự kiện như onComplete và vân vân.

18

JavaScript không có ngữ nghĩa khóa vì JS không phải là ngôn ngữ đa luồng. Nhiều luồng chỉ có thể hoạt động đồng thời trong các ngữ cảnh hoàn toàn khác biệt - ví dụ: Chuỗi công việc HTML5 hoặc trong nhiều thứ như đối tượng ngữ cảnh của JavaScriptCore API (tôi cho rằng SpiderMonkey có khái niệm tương tự). Họ không thể có trạng thái chia sẻ, vì vậy trong bản chất tất cả các thực hiện là nguyên tử.

Được rồi, như bây giờ bạn đã cung cấp một số mã của bạn tôi giả sử bạn có một cái gì đó tương tự như:

External Process: 
<JSObject>.isRunning = true; 
doSomething() 
<JSObject>.done() 

Hoặc một số ví dụ (sử dụng API thích hợp). Trong trường hợp này, tôi mong đợi động cơ JS chặn nếu JS đang thực thi trong ngữ cảnh đối tượng js của bạn (đó là những gì JavaScriptCore sẽ làm), không chắc rằng bạn có thể cần phải đặt một khóa thủ công tại chỗ xung quanh thực thi js.

Bạn đang sử dụng công cụ nào để thực hiện tất cả điều này? Tôi hỏi vì dựa trên mô tả của bạn, có vẻ như bạn đang đặt cờ từ chuỗi phụ từ ngôn ngữ không phải JS bằng cách sử dụng API C/C++ do ngôn ngữ đó cung cấp và hầu hết các công cụ JS giả định rằng mọi thao tác trạng thái được thực hiện qua API sẽ xảy ra trên một chuỗi đơn, thường là cùng một chuỗi mà tất cả việc thực thi xảy ra.

+0

Tôi đã thêm mã đầy đủ ở trên để làm cho nó rõ ràng hơn một chút. Động cơ là Webkit (safari). Từ javascript tôi gọi các quá trình bên ngoài, và quá trình bên ngoài gọi phương thức "done" khi nó được thực hiện. Về cơ bản, tôi cần đảm bảo chỉ có một quy trình bên ngoài chạy cùng một lúc. – Parand

+0

Giả sử bạn đang làm điều gì đó tương tự như [someObject call] hoặc JSObjectCallAsFunction (context, doneFunction, someObject), bạn nên đảm bảo rằng bạn đang gọi trên thread chính, đặc biệt nếu bạn đang sử dụng API ObjC JS do WebKit cung cấp (IIRC nó có thể phá vỡ một số ổ khóa) – olliej

+0

Bạn đã từng sử dụng sdk webkit trên iPhone chưa? Tôi đang sử dụng một sơ đồ window.location đơn giản, chưa thử SDK. Rất muốn tìm hiểu thêm về SDK. – Parand

0

Tôi có nội dung ajax điền danh sách lựa chọn, tôi cần nó để khóa vì vậy tôi đã làm một cái gì đó như thế này. Tôi nghĩ bạn có thể làm điều đó đơn giản hơn mặc dù sử dụng hoãn lại và đường ống hoặc một cái gì đó.

var semaphore=[]; 

function myFunc(arg){ 
    var dfd; 
    $.when(semaphore[table]).done(
     function(){ 
      dfd=myFuncInner(arg); 
     } 
    ); 
return dfd; 
} 

function myFuncInner(table){ 
semaphore[arg] = new $.Deferred(); 
... 
somethingasynchronous({ 
    semaphore[arg].resolve(); 
}); 

return semaphore[arg]; 
} 
0

Trước hết, trong khi javaScript là một luồng đơn, KHÔNG đúng là không có cơ chế tuần tự nào được yêu cầu bởi ứng dụng javaScript.

Ví dụ đơn giản, là khi nút gửi phải mờ dần trong một khoảng thời gian được đặt trong đó yêu cầu Ajax tới máy chủ đang hoạt động. Khi yêu cầu Ajax không đồng bộ hoàn tất thành công thì một thông báo sẽ xuất hiện ở nơi nút được sử dụng.

Mặc dù có thể hủy bỏ độ mờ của nút và chỉ cần đặt kiểu thành "display: none", ngay khi yêu cầu Ajax hoàn thành, điều đó là không thể trong jQuery. Ngoài ra, một giải pháp có thể sử dụng Sự kiện để đồng bộ hóa hai hoạt động đồng thời, nhưng về cơ bản là quá mức cần thiết cho một vấn đề đơn giản.

Giải pháp công nghệ thấp là thăm dò khóa và khi fadeout hoàn thành nó được mở khóa nhưng thông báo "server done" KHÔNG được hiển thị cho đến khi gọi lại thành công, như được đặt bởi $ .post, thực hiện.

var gl_lock; 
var gl_selfID; 

function poll_lock(message) { 
    if (gl_lock === 0) { 
      $('#output').text(message).fadeIn(200); 
      window.clearInterval(gl_selfID); 
    } 
} // end of poll_lock 

function worker() { 

    // no one gets in or out 
    gl_lock = 1; 

    $.post(..., data,function() { 
      gl_selfID = window.setInterval(poll_lock, 40, data.message); 
     }, "json"); 

    // end of fadeout unlock the semaphore 
    $('#submit-button').fadeOut(400, function() { gl_lock = 0; }); 

    } // end of worker 

Cuối cùng, tôi nghĩ đây là câu trả lời chi tiết hơn, dọc theo các dòng được đề xuất trong cuộc thảo luận này bởi perrohunter.