-
21-09-2019 - |
質問
私は常にダウンカウントタイマーがあるWebアプリケーションを持っています。一方、クライアントが頻繁に多くの時間をタイマーに追加されているかどうかを確認するためにサーバとチェックします。コードは次のようになります。
function tick() {
// This function is called once every second
time -= 1;
redisplay(time);
};
function update(newtime) {
// This function is called whenever the ajax request
// to the server yields a new time
time = newtime;
};
これは、当然のことながら、少し複雑よりもですが、固有の競合状態を見ることができます。どのようなアップデートやダニの機能の両方が同時にtime
を変更しようとしているか?
率直に言って、私は、同時実行の問題のこの種に対処する方法を理解するためにほぼ十分なJavaScriptを知らないのか?
ありがとうございます。
解決
あなたは、競合状態を持っていません。
別の非同期操作から別のコールバックを呼び出すことができます前に、コールバックが非同期操作(AJAX、setTimeout
、など)から発射されるたびに、そのコールバックが実行を終了しなければなりません。 update()
が実行されているのであれば、他のJavascriptではありません。 update()
が終了したら、非同期動作から他のコールバックは(例えば、tick()
)焼成することができます。興味深いことに、これはまた、なぜsetTimeout
であり、その同類がタイムアウトに達する正確な瞬間に実行することが保証されていません:他のいくつかのjavascriptのコールバックの実行をブロックすることができます。
http://ejohn.org/blog/how-javascript-timersをチェック-work / のすべてこれがどのように機能するかについていくつかの良い情報を参照してください。
他のヒント
Javascriptがシングルスレッドです。何の競合状態がありません。実行時にオーバーラップするtime = newtime;
とtime -= 1;
2ライン分のJavaScriptで方法はありません。実際には、二つの機能が重複しないことが保証されています。そのうちの一つが実行され、その後、他が実行されます。
私が間違っていた:これで問題が解決しません! (コードの後、について説明)の
NEWTIME = false;
function tick() {
// This function is called once every second
if (NEWTIME) {
time = NEWTIME;
NEWTIME = false;
}
time -= 1;
redisplay(time);
};
function update(newtime) {
// This function is called whenever the ajax request
// to the server yields a new time
NEWTIME = newtime;
};
この間違った解決策の問題であることをあなただけの変数time
に変数NEWTIME
からレースコンディションの問題を移動するこの方法をやってます。
ただ、このことを考える:tick
の実行は継続する前に、と呼ばれ、time = NEWTIME;
が値NEWTIME
を取得します更新し、今ラインX
に到達し、実行します。今ダニ実行はNEWTIME = false;
の実行を継続します。あなたがX
のNEWTIME
値と更新のような効果を失ってしまった。この方法で()を呼び出す!
問題は、いくつかのセマフォを必要とします。私は前回の1が終了した後に、AJAXを送信するためにその多くを行います。あなたの場合は少し似ている;)
そのような何かを試してみてください。これは、AJAXコールバックと衝突時間を減少するための試みをすべて無視してください。
window.TimeKeeper = new function(){
this.time=0; //initial value, whatever
this.isopen=true;
this.decrement = function(){
if(this.isopen){
this.time--;
redisplay(this.time);
}
}
this.set = function(val){
if(this.isopen){
this.isopen=false;
this.time=val;
this.isopen=true;
} else {
//another AJAX callback is modifying time.
//You can enqueue current value and put it later
}
}
}
function tick() {
TimeKeeper.decrement();
};
function update(newtime) {
TimeKeeper.set(newtime);
};
もう一つ - のsetTimeoutは、新しいスレッドのように動作し、私はブラウザが同期MEMのアクセスを行うことを期待するので、価値がデクリメントする前に成長しなかったかどうかを確認するために十分であるかもしれません。しかし、上記のソリューションは、より柔軟かつ安全である。
そして、もう一つの小さなヒント - あまりにも頻繁にAJAXを照会避ける - それは余分な問題が発生することがあり - 異なるために戻ってくるリクエストのように送られ、およびFirefoxのメモリ使用量があまりにも多くのAJAXの多くの分を構築するよりもを;)
限り、あなたはあなたの現在の時間にいくつかのより多くの秒を追加すると、あなたは問題ないはずです。
その代わりtime = newtime;
を行うのあなたが心配している秒を失うことはありません。この方法をtime += newtime;
てみます。
それでも、あなただけ失っている第二最悪でます。