2012-06-04 29 views
6

Tôi đã gặp sự cố lạ trong Firefox 12. setTimeout() dường như không phải chờ đợi độ dài phù hợp. Hoặc có lẽ đó là mili giây của ngày không jive?Firefox gọi hàm setTimeout quá sớm (hoặc Date.getTime() bị tắt?)

Check out this fiddle. Về cơ bản, một setTimeout 100ms dường như chạy bất cứ nơi nào giữa 80ms và 110ms. Tôi có thể hiểu thêm, dựa trên John Resig's explanation of timers. Nhưng ít hơn?

Bạn có thể phải làm mới nó một hoặc hai lần để xem vấn đề, vì đôi khi nó hoạt động chính xác trong lần chạy đầu tiên. Dường như nó hoạt động mạnh mẽ trong IE và Chrome.

Dưới đây là đoạn code tôi đang sử dụng trong fiddle tôi:

var txt = '', 
    TIMEOUT_LENGTH = 100, 
    _now; 

now = Date.now || function() { return new Date().getTime() }; 

function log(time) { 
    c = time < 100? 'class="error"' : ''; 
    $('#log').append('<p '+c+'>waited ' + time + '</p>'); 
} 

function defer() { 
    var d = $.Deferred(), 
     start = now(); 
    setTimeout(function() { 
     d.resolve(now() - start); 
    }, TIMEOUT_LENGTH); 
    return d.promise(); 
} 

for (var i = 0; i < 20; i++) { 
    defer().then(log); 
} 

Dưới đây là một mẫu của các đầu ra kỳ quặc:

enter image description here

Dưới đây là thông tin trình duyệt của tôi:

enter image description here

Và cảm ơn rất nhiều h để đọc câu hỏi của tôi! Tôi hy vọng ai đó có thể làm sáng tỏ điều này.

INFO THÊM

tôi làm việc xung quanh vấn đề bằng cách sử dụng setInterval() và kiểm tra mỗi increment để xem thời gian cần thiết đã trôi qua. See this fiddle.

Tuy nhiên, tôi vẫn rất muốn nghe nếu có ai đó có thể làm sáng tỏ nguồn gốc của sự cố

+1

Tôi có thể xác nhận hành vi này trong Firefox 12 trên OS X 10.7. Safari cung cấp bất cứ nơi nào giữa 100 và 105 cho tôi, Firefox 12 80s-110s cho lần chạy đầu tiên, chạy tiếp theo là ... 95-105. – Aaron

+0

Vui mừng khi biết đó không chỉ là tôi :) – Kato

+0

Vì vậy, đó là tất cả những gì chúng tôi nhận được sau đó. Có lẽ tôi sẽ mở ra một lỗi trên tại mozilla chỉ để xem những gì họ nói :) – Kato

Trả lời

3

Có. Độ chính xác của setTimeout dựa trên nhiều yếu tố và không được đảm bảo luôn thực thi vào đúng thời điểm bạn chỉ định.

Tôi không thể nói điều này với bất kỳ cơ quan nào, nhưng tôi sẽ nguy hiểm khi đoán Firefox có vẻ nhanh hơn, sẽ tăng tốc động cơ JS tạm thời để mọi thứ chuyển động (điều này thật thú vị, bởi vì theo kinh nghiệm của tôi , các chức năng dựa trên bộ đếm thời gian thực sự chạy chậm hơn lúc ban đầu trong phiên bản firefox của tôi).

Không setTimeout cũng không setInterval hứa rằng chúng sẽ thực thi đúng thời điểm, như liên kết bạn đã đăng nêu. Tuy nhiên, với setInterval, bạn sẽ có được lợi ích của vòng lặp hẹn giờ làm những gì có thể để "sửa chính nó" bằng cách bắt kịp nếu nó quá chậm phía sau, vì vậy cho bất kỳ điều gì bạn đang cố gắng làm, nó có thể phù hợp hơn.

Dù sao, đây là kết quả của tôi trên Macbook của tôi 10.6.8:

Firefox 5.0.1:

waited 92 
waited 92 
waited 93 
waited 93 
waited 93 
waited 93 
waited 93 
waited 94 
waited 93 
waited 93 
waited 93 
waited 93 
waited 94 
waited 94 
waited 94 
waited 94 
waited 94 
waited 95 
waited 96 
waited 96 

Safari 5.1.5:

waited 100 
waited 104 
waited 104 
waited 103 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 

Chrome 19.0.1084.52:

waited 101 
waited 103 
waited 103 
waited 104 
waited 104 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 103 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
waited 104 
+0

FWIW, 'setInterval' là cách tôi đã giải quyết vấn đề. Tôi chỉ kiểm tra các khoảng thời gian trên mỗi đánh dấu và đóng một lần 100ms đã đạt được, để đảm bảo rằng nó không giảm xuống dưới mức tối thiểu. Tuy nhiên, đây vẫn là một vấn đề rất hấp dẫn mà tôi muốn nghe một lời giải thích cho (vì nó có vẻ như nó không bao giờ nên chạy trước khi chiều dài thiết lập). – Kato

+0

Ngoài ra, việc thiếu người phàn nàn về vấn đề này là một chút đáng ngạc nhiên, vì vậy tôi vẫn tò mò nếu tôi thiếu điều gì đó rõ ràng :) – Kato

+0

Chỉ cần sang một bên, Firefox 5 là khá 'cũ' tại thời điểm này xem xét bạn có Safari và Chrome được cập nhật. – Aaron

1

JavaScript là đồng bộ ous.Trình duyệt sẽ thêm setTimeout của bạn vào hàng đợi và thực hiện chúng sau

  1. sự đếm ngược kết thúc
  2. Nó đã hoàn thành bất kỳ nhiệm vụ khác có trong hàng đợi vào lúc này đếm ngược kết thúc.
+1

Xin cảm ơn! Thật không may, điều đó không thực sự giải thích tại sao nó sẽ gọi hàm trước thời gian được chỉ định trong 'setTimeout' hoặc tại sao Firefox hoạt động khác với các trình duyệt khác. – Kato

1

Tôi đã viết hàm sau để đảm bảo mã của tôi được thực thi sau ít nhất một lượng mili giây nhất định. Tôi sử dụng nó thay vì setTimeout

mySetTimeout=function(f,t){ 
    var endTime=new Date().valueOf()+t; 
    setTimeout(function(){ 
     var now=new Date().valueOf(); 
     if(now<endTime){ 
      mySetTimeout(f,endTime-now); 
     }else{ 
      f(); 
     } 
    },t); 
}; 
Các vấn đề liên quan