2011-02-02 35 views
20

Tôi nhận thấy rằng nếu tôi đặt setTimeout trong 1 phút trong tương lai và sau đó thay đổi thời gian hệ thống của tôi thành 5 phút trước, chức năng setTimeout sẽ kích hoạt sau 6 phút .JavaScript setTimeout và thay đổi về các vấn đề gây ra thời gian hệ thống

Tôi đã làm điều này là vì tôi muốn xem điều gì xảy ra trong khi thay đổi tiết kiệm ánh sáng ban ngày sang đồng hồ hệ thống.

Trang web JavaScript của tôi sử dụng chức năng setTimeout để tự động làm mới trang sau mỗi 5 giây và nếu tiết kiệm ánh sáng ban ngày xảy ra thì thông tin trang sẽ bị đóng băng trong một giờ. Có cách giải quyết nào không?

Chỉnh sửa: Tôi đang cập nhật trang bằng Ajax, tôi không muốn làm mới toàn bộ trang.

+0

Bạn đang sử dụng trình duyệt nào? –

+8

Khi thay đổi Thời gian tiết kiệm ánh sáng ban ngày xảy ra, đó thực sự là thay đổi bù trừ múi giờ, không thay đổi thành UTC. Kiểm tra bạn thực hiện không mô hình những gì thực sự xảy ra nếu DST được xử lý tự động bởi hệ thống. [Leap seconds] (http://en.wikipedia.org/wiki/Leap_second) có thể vẫn là một vấn đề, tuy nhiên, như một đồng bộ hóa thời gian tự động nếu đồng hồ của máy tính đã trôi xa thời gian thực (vì vậy nó sẽ không dần dần thay đổi thời gian). – PleaseStand

+0

Tôi vừa thử nghiệm điều này trong IE7, IE8, IE9, Firefox và Chrome trên Windows 7 và tôi không thấy hành vi bạn mô tả. Có lẽ điều này là cụ thể cho hệ điều hành? – gilly3

Trả lời

4

Điều tôi sẽ làm là thay đổi từ việc mở một yêu cầu Ajax mới cứ sau 5 giây để sử dụng Comet (bỏ phiếu dài). Nó là một lựa chọn tốt hơn bởi vì máy chủ sẽ đẩy các kết quả mới vào trình duyệt mỗi khi chúng cần thiết, điều này có thể là mỗi 5 giây ở phía máy chủ hoặc mỗi khi có thông tin mới.

Thậm chí tốt hơn là nên sử dụng ổ cắm web và có Comet khi bị thu gọn. Việc này rất dễ triển khai với Faye hoặc socket.oi.

Có các tùy chọn khác, như CometD o Ape.

+0

+1 cho websockets. – Raynos

0

Bạn có thể sử dụng làm mới thẻ meta để thực hiện việc này. Mã này sẽ làm mới trang sau mỗi 5 giây:

<meta http-equiv="refresh" content="5"> 

Đối với câu hỏi javascript, nó có thể chỉ là cách trình duyệt xử lý setTimeout. Nó nói với trình duyệt để thực thi mã tại một thời gian đặt, và sau đó khi đồng hồ thay đổi, mã vẫn thực hiện tại thời điểm trước khi thay đổi theo dõi? Chỉ cần đoán, nhưng tôi sẽ phải giữ điều đó trong tâm trí lần sau tôi sử dụng setTimeout.

Chỉnh sửa: Ok, điều đó sẽ không hoạt động đối với ajax Chỉnh sửa lại: Đây thực sự là một câu hỏi hay. Tôi chắc chắn rằng các chức năng setTimeout như tôi đã nói ở trên, nhưng wow, đây là một lời trêu ghẹo não.

+0

Tôi đã chỉnh sửa câu hỏi của mình để thêm rằng tôi đang sử dụng Ajax để cập nhật trang và không thể làm mới nó. –

4

Sử dụng setInterval thay vì setTimeout và các vấn đề của bạn nên được giải quyết :)

Cập nhật:

Nếu bạn thực sự không thể sử dụng một trong hai setTimeout hoặc setInterval, bạn có thể thử để có một ẩn iframe rằng tải một HTML đơn giản trang trông giống như sau:

<html> 
    <head> 
     <meta http-equiv="refresh" content="300"/> 
     <script> 
      document.domain='same as parent page'; 
      top.ajax_function_you_wish_to_trigger(); 
     </script> 
    </head> 
    <body> 
    </body> 
</html> 

Nếu bạn may mắn làm mới meta sẽ không gây ra vấn đề tương tự.

Một giải pháp khác là di chuyển quá trình kích hoạt sự kiện đến máy chủ qua server push. Có nhiều lý do để không làm điều này, không phải là ít nhất bạn sẽ tập trung các sự kiện và làm cho chúng trở thành gánh nặng trên máy chủ, nhưng nó có thể được coi là phương sách cuối cùng.

+0

Thật không may điều này đã không giải quyết vấn đề này. Điều tương tự cũng xảy ra. –

+0

SetInterval không may là tồi tệ hơn đáng kể. – Raynos

+0

Thats lạ - bạn đang sử dụng hệ điều hành nào? Tôi không thể tái tạo vấn đề này với setInterval trên win7 64bit trong bất kỳ trình duyệt nào. –

0

Bạn có thể di chuyển và thực hiện kiểm tra if (Date in range foo). Về cơ bản, kiểm tra xem tem thời gian hiện tại có trong vòng 5 giây của giờ tiết kiệm ánh sáng ban ngày và sau đó chỉ cần làm mới trang ngay lập tức thay vì sau đó bằng cách sử dụng setTimeout.

Bằng cách này, người dùng nhận được một chút khó chịu nhỏ gần thay đổi thời gian đã biết nhưng trang sẽ không bị đóng băng trong một giờ.

1

Gần đây, tôi đã gặp sự cố này. Trong trường hợp của tôi thay đổi thời gian có thể gây ra tài chính nghiêm trọng mất vì vậy tôi đã phải thực hiện nó nghiêm túc.

Một số nền:

  • IE và Opera xử lý sự thay đổi hệ thống thời gian đúng cách (không tác dụng phụ để setTimeout, setInterval).
  • FF < 4.0 và tất cả trình duyệt dựa trên Webkit không xử lý được thời gian thay đổi trong quá khứ (chính xác như bạn mô tả). Lưu ý: bộ hẹn giờ trong Chrome tuy nhiên chỉ dừng sau một thời gian ~ 2-60 giây.

Giải pháp của tôi: sử dụng một số sự kiện từ tương tác người dùng (ví dụ: mousemove, mouseove, v.v ...) để kích hoạt kiểm tra thay đổi thời gian.

Clock.prototype.checkLocalTime = function(){ 
var diff = Date.now()- this.lastTimestamp; 
if (diff < 0 || diff > 20000) { // if time shifted back or more than 20s to the future 
    console.warn('System time changed! By ' + diff + 'ms'); 
    this.restartTimer(); 
    this.getServerTime(); 
} 
this.lastTimestamp = time; 

}

Như bạn có thể thấy tôi khởi động lại bộ đếm thời gian và đồng bộ hóa thêm thời gian với máy chủ.

Các vấn đề liên quan