2010-01-19 40 views
6

Bạn có thể tạm dừng thực thi JavaScript mà không cần khóa trình duyệt không? Cách bạn sẽ tạm dừng thực hiện là thực hiện một vòng lặp vô hạn while(), nhưng trong trường hợp của FireFox, nó sẽ khóa trình duyệt cho đến khi vòng lặp kết thúc.Tạm dừng thực thi JavaScript mà không cần khóa trình duyệt

Bạn sẽ làm gì với điều này?


Tôi đang cố gắng ghi đè window.confirm() để triển khai hộp thoại của riêng mình bằng HTML. Tôi đang làm điều này vì vậy tôi không phải thay đổi mã hiện tại (đó là một mã code-base khá lớn).

Tôi cần có khả năng tạm dừng thực thi để cho phép người dùng nhập; để lần lượt trả về một boolean như chức năng xác nhận tiêu chuẩn thực hiện:

if (confirm("...")) 
{ 
    // user pressed "OK" 
} 
else 
{ 
    // user pressed "Cancel" 
} 



Cập nhật

Theo hiểu biết của tôi; điều này không thể được thực hiện bằng cách sử dụng setTimeout() hoặc setInterval() vì các hàm này thực thi mã được cung cấp cho chúng một cách không đồng bộ.

+2

'setTimeout' và' setInterval' * không * thực thi mã không đồng bộ, họ đếm xuống và sau đó thêm chức năng gọi lại vào một hàng đợi được gọi khi luồng không hoạt động. Các chức năng tự chạy sau đó đồng bộ. –

+0

Xem thêm: http://stackoverflow.com/questions/2056747/javascript-puzzle-to-solve-window-confirm-divconfirmstrmessage –

+3

@Andy E - 'window.setTimeout' (và' window.setInterval') tạo các cuộc gọi lại không đồng bộ . Luồng chương trình bình thường tiếp tục ngay lập tức sau khi gọi nó và cuộc gọi lại được thực hiện vào một ngày sau đó, tùy thuộc vào độ dài bộ đếm thời gian. Thực tế là JavaScript là đơn luồng và gọi lại, khi nó đã bắt đầu thực hiện, sau đó chặn các mã khác khỏi thực thi không ngăn không cho nó không đồng bộ. –

Trả lời

8

confirm()prompt()alert() là các chức năng đặc biệt - chúng gọi ra khỏi hộp cát JavaScript vào trình duyệt và trình duyệt tạm ngừng thực thi JavaScript. Bạn không thể làm điều tương tự, vì bạn cần xây dựng chức năng của mình thành JavaScript.

Tôi không nghĩ rằng có một cách tuyệt vời để thả trong một sự thay thế mà không làm một số chuyển dịch cơ cấu dọc theo dòng:

myconfirmfunction(function() { 
    /* OK callback */ 
}, function() { 
    /* cancel callback */ 
}); 
+0

Tôi đã cập nhật câu hỏi của mình. Có một cái nhìn. – roosteronacid

2

theo cách bạn thường ngừng thi công nên hầu như không bao giờ là một vô hạn trong khi vòng lặp.

chia tay công việc của bạn thành nhiều phần, mà bạn gọi với setTimeout

thay đổi này:

DoSomeWork(); 
    Wait(1000); 
    var a = DoSomeMoreWork(); 
    Wait(1000); 
    DoEvenMoreWork(a); 

này:

DoSomeWork(); 
setTimeout(function() { 
    var a = DoSomeMoreWork(); 
    setTimeout(function() { 
     DoEvenMoreWork(a); 
    }, 1000); 
}, 1000); 
+0

Tôi đã cập nhật câu hỏi của mình. Có một cái nhìn. – roosteronacid

7

Bạn không thể dừng thread sự kiện trong JavaScript, vì vậy thay vào đó bạn phải giải quyết vấn đề, thường là bằng cách sử dụng các hàm gọi lại. Đây là các hàm được chạy sau này, nhưng có thể được truyền xung quanh giống như bất kỳ đối tượng nào khác trong JavaScript. Bạn có thể quen thuộc với họ từ lập trình AJAX. Vì vậy, ví dụ:

doSomeThing(); 
var result = confirm("some importart question"); 
doSomeThingElse(result); 

sẽ được chuyển đổi thành:

doSomeThing(); 
customConfirm("some importart question", function(result){ 
    doSomeThingElse(result); 
}); 

nơi customConfirm bây giờ có một câu hỏi và chuyển kết quả đến chức năng phải mất như một cuộc tranh cãi. Nếu bạn triển khai hộp thoại DOM bằng nút, sau đó kết nối trình xử lý sự kiện với các nút OK và CANCEL và gọi hàm gọi lại khi người dùng nhấp vào một trong số họ.

+1

");" bị thiếu ở cuối mã của bạn. – Frunsi

1

Tôi không nghĩ có cách nào để tạo lại chức năng của hàm confirm() hoặc prompt() một cách hợp lý trong JavaScript của riêng bạn.Chúng "đặc biệt" theo nghĩa là được thực hiện như các cuộc gọi vào thư viện trình duyệt gốc. Bạn có thể không thực sự làm một hộp thoại phương thức của loại đó trong JavaScript.

Tôi đã thấy các thư viện giao diện người dùng khác nhau mô phỏng hiệu ứng bằng cách đặt một phần tử lên đầu trang, trông giống như một hộp thoại phương thức, nhưng được thực hiện bằng cách sử dụng gọi lại không đồng bộ.

Bạn sẽ phải sửa đổi thư viện hiện có, thay vì thay thế window.confirm.

7

Hoặc sử dụng gọi lại hoặc làm cho mã của bạn chỉ Firefox. Trong Firefox có hỗ trợ JavaScript 1.7 trở lên, bạn có thể sử dụng câu lệnh yield để mô phỏng hiệu ứng mong muốn của mình. Tôi đã tạo một thư viện cho mục đích này được gọi là async.js. Các thư viện chuẩn cho async.js bao gồm một phương pháp xác nhận, có thể được sử dụng như ví dụ:

if (yield to.confirm("...")) { 
    // user pressed OK 
} else { 
    // user pressed Cancel 
} 
0

tôi đã cố gắng sử dụng vòng lặp chặt chẽ cho this. Tôi cần phải làm chậm sự kiện gốc (AFAIK là trường hợp sử dụng duy nhất cho một sự chờ đợi đồng bộ mà không thể được tái cấu trúc không đồng bộ). Có rất nhiều ví dụ vòng ra có yêu cầu bồi thường không để khóa trình duyệt; nhưng không ai trong số họ làm việc cho tôi (trình duyệt đã không khóa, nhưng họ ngăn nó làm điều tôi đang chờ đợi ở nơi đầu tiên), vì vậy tôi đã từ bỏ ý tưởng.

Tiếp theo tôi đã thử this - lưu trữ và phát lại sự kiện, có vẻ như không thể duyệt qua được. Tuy nhiên tùy thuộc vào sự kiện và mức độ linh hoạt bạn cần, bạn có thể đến gần.

Cuối cùng tôi đã từ bỏ và cảm thấy tốt hơn cho nó; Tôi tìm thấy một cách để làm cho mã của tôi hoạt động mà không phải làm chậm sự kiện gốc.

3

Có một phần mở rộng cho ngôn ngữ JavaScript có tên là StratifiedJS. Nó chạy trong mọi trình duyệt và cho phép bạn thực hiện điều đó: tạm dừng một dòng mã JavaScript mà không đóng băng trình duyệt.

Bạn có thể bật JavaScript được phân tầng, ví dụ: bằng cách bao gồm Oni Apollo (http://onilabs.com/docs) trong trang web của bạn như:

<script src="http://code.onilabs.com/latest/oni-apollo.js"></script> 
<script type="text/sjs"> your StratifiedJS code here </script> 

Mã của bạn sẽ trông như thế này:

var dom = require("dom"); 
displayYourHtmlDialog(); 
waitfor { 
    dom.waitforEvent("okbutton", "click"); 
    // do something when the user pressed OK 
} 
or { 
    dom.waitforEvent("cancelbutton", "click"); 
} 
hideYourHtmlDialog(); 
// go on with your application 
Các vấn đề liên quan