22

setTimeoutを1 分間未来に設定し、システム時間を過去 5 分間に変更すると、setTimeout関数は 6 分後にトリガーされることに気付きました。

これを行ったのは、システム クロックへの夏時間の変更中に何が起こるかを確認したかったからです。

私の JavaScript Web ページは、setTimeout5 秒ごとにページを自動的に更新する機能を使用しており、サマータイムが発生すると、ページ情報が 1 時間フリーズします。回避策はありますか?

編集: Ajax を使用してページを更新しています。ページ全体を更新したくありません。

4

6 に答える 6

4

setInterval代わりに使用するsetTimeoutと、問題が解決するはずです:)

アップデート:

本当に setTimeout も setInterval も使用できない場合は、iframe次のような単純な HTML ページをロードする隠しオブジェクトを作成してみてください。

<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>

運が良ければ、メタ リフレッシュによって同じ問題が発生することはありません。

もう 1 つの解決策は、 server pushを介してイベント発生をサーバーに移動することです。これを行わない理由はたくさんありますが、イベントを一元化してサーバーに負担をかけることはもちろん、最後の手段と見なすこともできます。

于 2011-02-02T23:05:03.680 に答える
4

私がやろうとしているのは、5 秒ごとに新しい Ajax リクエストを開くことから、Comet (ロング ポーリング) を使用するように変更することです。サーバーは新しい結果が必要になるたびにブラウザーにプッシュするため、より良いオプションです。これは、サーバー側で 5 秒ごと、または新しい情報が利用可能になるたびに行うことができます。

さらに良いのは、Web ソケットを使用し、Comet をフォールバックとして使用することです。これはFayeまたはsocket.ioで簡単に実装できます。

CometD や Ape など、他のオプションもあります。

于 2011-02-13T20:56:52.553 に答える
2

私も最近この問題に遭遇しました。私の場合、時間の変更は重大な経済的損失を引き起こす可能性があるため、真剣に受け止めなければなりませんでした。

背景:

  • setTimeout()IE と Opera は、システムの時間変更を適切に処理します ( 、 への副作用はありませんsetInterval())。
  • FF < 4.0 およびすべての Webkit ベースのブラウザーは、過去への時間の変更を処理できません (まさにあなたが説明したとおり)。注: Chrome のタイマーは、2 ~ 60 秒後にしか停止しません。

私の解決策: ユーザー インタラクション (つまり、、など) からのイベントを使用してmousemovemouseover時間変更チェックをトリガーします。

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;
}

お気づきのとおり、タイマーを再起動し、さらに時刻をサーバーと同期します。

于 2011-02-20T20:14:16.457 に答える
1

window.performanceを使用すると、より正確な結果が得られ、システム時刻が変更されたときに一貫性が保たれることがわかりました。

カウントダウン タイマーがシステム時間の変更の影響を受けないように、setInterval ティック内で現在の時間を取得する方法としてこれを使用しました。システムクロックを変更することにより、タイマーの不正行為を防止する(より多くの時間を取得する)ことを試みるために、特定の時間からのティック数に基づいて計算していました

getCurrentTime = () => {
  return window.performance ?
    performance.timing.navigationStart + performance.now() : Date.now();
}

tick() {
  let now = this.getCurrentTime();

  if (this.calibrateTime) { //calibrate with a given server time
    now -= this.timeCalibration;
  }

  const elapsedSeconds = (now - this.startedAt) / 1000;

  if (elapsedSeconds > this.props.timeLimit + this.props.submitBuffer) {
    clearInterval(this.interval);
    this.props.onTimeUp();
  }

  let secondsRemaining = this.props.timeLimit - Math.floor(elapsedSeconds);
  if (secondsRemaining < 0) secondsRemaining = 0;

}

startTimer() {
  if (!this.startedAt) {
    this.startedAt = Date.now();
  }

  this.setState({ started: true }, () => {
    this.interval = setInterval(this.tick.bind(this), 500);
  });
}
于 2018-03-23T14:44:00.183 に答える
0

これを行うには、メタ タグの更新を使用できます。このコードは、5 秒ごとにページを更新します。

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

JavaScript の質問に関しては、ブラウザが setTimeout を処理する方法にすぎない可能性があります。設定された時間にコードを実行するようにブラウザに指示し、時計が変わると、時計が変わる前の時間にコードが実行されますか? 推測ですが、次回 setTimeout を使用するときはそのことを覚えておく必要があります。

編集: わかりました、それは ajax では機能しません もう一度編集: これは本当に良い質問です。上記のように setTimeout が機能することは確かですが、うわー、これは頭の体操です。

于 2011-02-02T22:56:35.590 に答える
0

ファッジしてif (Date in range foo)チェックを行うことができます。基本的に、現在のタイム スタンプが夏時間の 5 秒以内にあるかどうかを確認し、.xml を使用するのではなく、すぐにページを更新しますsetTimeout

このようにすると、ユーザーは既知の時間変更の近くで多少の不快感を覚えますが、ページが 1 時間フリーズすることはありません。

于 2011-02-13T20:58:57.043 に答える