2013-03-29 55 views
5

Tôi đang làm việc trên một ứng dụng web rất nhạy cảm với thời gian. Một trong những quy tắc kinh doanh được trao cho tôi là hành vi của ứng dụng phải luôn phụ thuộc vào thời gian trên máy chủ web, bất kể thời gian nào là trên đồng hồ của khách hàng. Để làm rõ điều này với người dùng, tôi được yêu cầu hiển thị thời gian của máy chủ trong ứng dụng web.Hiển thị thời gian của một máy tính khác trên trang web bằng Javascript?

Để kết thúc này, tôi đã viết mã Javascript sau:

clock = (function() { 
var hours, minutes, seconds; 

function setupClock(updateDisplayCallback) { 
    getTimeAsync(getTimeCallback); 

    function getTimeCallback(p_hours, p_minutes, p_seconds) { 
     hours = p_hours; 
     minutes = p_minutes; 
     seconds = p_seconds; 
     setInterval(incrementSecondsAndDisplay, 1000); 
    } 

    function incrementSecondsAndDisplay() { 
     seconds++; 
     if (seconds === 60) { 
      seconds = 0; 
      minutes++; 
      if (minutes === 60) { 
       minutes = 0; 
       hours++; 
       if (hours === 24) { 
        hours = 0; 
       } 
      } 
     } 
     updateDisplayCallback(hours, minutes, seconds); 
    } 
} 

// a function that makes an AJAX call and invokes callback, passing hours, minutes, and seconds. 
function getTimeAsync(callback) { 
    $.ajax({ 
     type: "POST", 
     url: "Default.aspx/GetLocalTime", 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     success: function (response) { 
      var date, serverHours, serverMinutes, serverSeconds; 
      date = GetDateFromResponse(response); 
      serverHours = date.getHours(); 
      serverMinutes = date.getMinutes(); 
      serverSeconds = date.getSeconds(); 
      callback(serverHours, serverMinutes, serverSeconds); 
     }  
    }) 
} 

return { 
    setup: setupClock 
}; 
})(); 

Chức năng thông qua vào cho updateDisplayCallback là một chức năng đơn giản để hiển thị ngày trên trang web.

Ý tưởng cơ bản là Javascript thực hiện cuộc gọi không đồng bộ để tra cứu thời gian của máy chủ, lưu trữ nó trên máy khách và sau đó cập nhật nó một lần mỗi giây.

Lúc đầu, điều này dường như hoạt động, nhưng khi thời gian trôi qua, thời gian hiển thị sẽ mất sau vài giây mỗi phút. Tôi để nó chạy qua đêm, và khi tôi đến vào sáng hôm sau, nó đã tắt hơn một giờ! Điều này hoàn toàn không được chấp nhận vì ứng dụng web có thể được mở trong nhiều ngày tại một thời điểm.

Làm cách nào để sửa đổi mã này để trình duyệt web liên tục hiển thị chính xác thời gian của máy chủ?

+0

Có thể là một tùy chọn để thực hiện cuộc gọi ajax một lần mỗi phút hoặc lâu hơn, để đồng bộ hóa với máy chủ không? –

+0

lưu ý rằng yêu cầu đến máy chủ cần có thời gian để bạn có thể thêm vài trăm ms mỗi khi bạn thực hiện cuộc gọi. – charlietfl

+0

setInterval KHÔNG CHÍNH XÁC. Tạo sự khác biệt từ thời gian máy chủ và thời gian trên đồng hồ máy tính. Thêm sự khác biệt đó vào đồng hồ của người dùng. Cũng nhớ độ trễ của các cuộc gọi http có thể gây ra thời gian để được giảm giá rất nhiều. Phải mất thời gian để đi du lịch các ống. – epascarello

Trả lời

0

Cảm ơn câu trả lời. Tôi đã bỏ phiếu cho cả hai câu trả lời cho đến nay vì chúng chứa thông tin hữu ích. Tuy nhiên, tôi không sử dụng câu trả lời chính xác được quy định trong cả hai câu trả lời.

Điều cuối cùng tôi quyết định là hơi khác một chút.

Tôi đã viết về những gì tôi đã học được trên số personal web page của mình.

Trước hết, bây giờ tôi hiểu rằng việc sử dụng setInterval(..., 1000) không đủ tốt để thực hiện điều gì đó một lần mỗi giây trong một thời gian dài. Tuy nhiên, 'bỏ ​​phiếu' thời gian với một khoảng thời gian ngắn hơn nhiều tìm kiếm thứ hai để thay đổi có vẻ rất không hiệu quả với tôi.

Tôi quyết định rằng việc theo dõi 'bù trừ' giữa thời gian máy chủ và thời gian máy khách là điều có ý nghĩa.

giải pháp cuối cùng của tôi là phải làm như sau:

(1) Do một cuộc gọi AJAX đến máy chủ để có được thời gian. Hàm này cũng kiểm tra thời gian của máy khách và tính toán sự khác biệt giữa thời gian máy chủ và thời gian máy khách, tính bằng mili giây. Do độ trễ mạng và các yếu tố khác, lần tìm nạp ban đầu này có thể bị tắt một vài giây. Vì mục đích của tôi, điều này là ổn.

(2) Thực hiện chức năng tick. Mỗi lần thực hiện tick, nó sẽ kiểm tra xem nó đã được thực hiện bao lâu kể từ lần cuối cùng thực hiện tick. Nó sẽ sử dụng thời gian này để tính một đối số được chuyển đến setTimeout để hiển thị thời gian được cập nhật khoảng một lần mỗi giây.

(3) Mỗi ​​lần hàm tick tính toán thời gian được hiển thị, phải mất thời gian khách hàng và thêm sự khác biệt được tính trong bước (1). Bằng cách này, tôi không phụ thuộc vào khách hàng để có thời gian thiết lập một cách chính xác, nhưng tôi phụ thuộc vào khách hàng để đo chính xác thời gian trôi qua. Vì mục đích của tôi, điều này là ổn. Điều quan trọng nhất là bất kể cách setTimeout có thể không chính xác hoặc bị gián đoạn bởi các quy trình khác (chẳng hạn như hộp thoại phương thức), thời gian được hiển thị phải luôn chính xác.

+0

Đừng quên rằng thời gian người dùng có thể nhảy bất ngờ. Điều này có thể được khởi tạo thủ công bởi người dùng, bởi một khách hàng NTP hoặc do thay đổi thời gian tiết kiệm múi giờ/ánh sáng ban ngày. Giả sử ít nhất một số người dùng sẽ không ở cùng một nơi với máy chủ của bạn, điều cuối cùng đặc biệt có vấn đề vì thời gian thay đổi theo mức tăng lớn. Nó cũng có nhiều khả năng xảy ra vì ứng dụng của bạn là một ứng dụng chạy dài. May mắn thay, nó cũng có thể giải quyết được mà không cần thực hiện các cuộc gọi máy chủ phụ bằng cách sử dụng phương thức getTimezoneOffset() ngoài hàm getTime(). – jerry

2

setInterval không phải là cách đáng tin cậy để lên lịch cho các sự kiện quan trọng thời gian. Có thể mất ít hơn hoặc nhiều hơn 1000ms để chạy lại cuộc gọi của bạn tùy thuộc vào mức độ JavaScript hiện tại đang bận.

Một cách tiếp cận tốt hơn sẽ là thực hiện một khoảng thời gian ngắn hơn và sử dụng new Date().getTime() để kiểm tra xem giây đã trôi qua chưa.

Trình duyệt khoảng thời gian tối thiểu cho phép là cao 10.

+0

Có rất nhiều trang web hiện có mà làm thời gian hiển thị, do đó, có vẻ như có phải là một thực hành tốt nhất cho việc này. –

+0

Nó sẽ không bao giờ mất ít thời gian hơn quy định. Ngoài ra, khoảng thời gian tối thiểu không phải là 10ms. Nó phụ thuộc vào trình duyệt. –

+1

Tôi sẽ hiệu chỉnh từng phút để tránh các vấn đề bất kể tôi đã sử dụng phương pháp nào. –

6

Bộ đặt trước của Javascript không đủ chính xác để cho phép bạn giữ thời gian như thế này.

Giải pháp của tôi sẽ là:

  1. Định kỳ lấy thời gian của máy chủ trong mili giây (nó không cần phải được thường xuyên như hai đồng hồ sẽ hầu như không đi chệch rằng nhiều)
  2. Lấy thời gian khách hàng trong mili giây
  3. Tính độ lệch đồng hồ giữa máy chủ và máy khách (client-server)
  4. Định kỳ cập nhật màn hình hiển thị của đồng hồ bằng cách lần khách hàng và thêm độ lệch đồng hồ

Chỉnh sửa: Để chính xác hơn, bạn có thể đo thời gian chuyến đi khứ hồi của yêu cầu của máy chủ, chia cho 2 và yếu tố làm chậm độ lệch đồng hồ. Giả sử các chuyến đi khứ hồi là đối xứng trong thời gian của chúng, điều này sẽ đưa ra một phép tính chính xác hơn.

+0

1. ... NHƯNG thời gian cho yêu cầu http Ajax đến máy chủ sẽ khác nhau rất nhiều giữa các cuộc gọi dựa trên lưu lượng mạng. – epascarello

+0

Điều này có vẻ là một giải pháp thanh lịch hơn, vì nó có nghĩa là bạn không viết đồng hồ của riêng bạn trong 'incrementSecondsAndDisplay()' mà bạn đang sử dụng 'Date' được xây dựng trên máy khách. –

+0

@epascarello bạn sẽ sử dụng thời gian máy khách khi phản hồi của máy chủ xuất hiện tất nhiên, không phải khi yêu cầu được gửi. –

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