Параллелизм Аякса

У меня есть веб-приложение, где есть таймер, который постоянно считает в обратном порядке. Между тем клиент часто сверяется с сервером, чтобы видеть, было ли больше времени добавлено к таймеру. Кодекс выглядит примерно так:

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 понимает, как иметь дело с этим видом проблемы параллелизма: есть ли легкий способ сделать это, или в противном случае кто-то может указать мне к ресурсам, где я могу узнать больше?

Спасибо.

16
задан Justin Johnson 16 January 2010 в 18:06
поделиться

5 ответов

У вас нет состояния гонки, потому что JavaScript не выполняется одновременно.

Каждый раз, когда обратный вызов уволен из асинхронизации (Ajax, Settimeate , и т. Д.), Этот обратный вызов должен завершить выполнение выполнения, прежде чем можно назвать другой обратный вызов от другой операции ASYNC. Так что если работает обновление () , работает ни один другой JavaScript. Как только Обновление () Отделка, другие обратные вызовы от Async-операций могут быть уволены (например, Tick () ). Интересно, что это также поэтому Settimeate и его ILK не гарантированно выполнено в точном моменте, присвоенный тайм-ауту: какой-то другой JavaScript может быть заблокировать выполнение обратного вызова.

Проверьте http://ejohn.org/blog/how-javascript-timers-work/ Для какой-то хорошей информации о том, как все это работает.

16
ответ дан 30 November 2019 в 22:10
поделиться

До тех пор, пока вы добавляете еще несколько секунд до текущего времени, вы должны быть в порядке.

Вместо того, чтобы сделать время = NewTime; попробуйте время + = NewTime; Таким образом, вы не потеряете второе, вы беспокоитесь.

Тем не менее, вы теряете только секунду в худшем случае.

-2
ответ дан 30 November 2019 в 22:10
поделиться

Я был неправ: это не решает проблему! (Объяснение после кода)

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

Проблема с этим неправильным решением является то, что вы просто переместите проблему состояния гонки из вариабели для переменной Newtime .

Просто подумайте, что это: исполнение THIC достигает и выполняет строку Time = NewTime; Теперь, прежде чем продолжить, обновление звонится и Newime значение x . Теперь оформление тикания продолжается выполнение NewTime = false; . Таким образом, вы потеряли x значение Newime и поэтому эффект вызова обновления ()!

0
ответ дан 30 November 2019 в 22:10
поделиться

JavaScript - это отдельная резьба. Там нет состояния расы. В JavaScript нет никаких способов Time = Newime; и время - = 1; для перекрытия во время выполнения. На самом деле, две функции гарантированно не перекрываются. Один из них будет бегать, а затем другой будет работать.

8
ответ дан 30 November 2019 в 22:10
поделиться

Проблема требует семафоров. Я делаю это часто за то, что посылаю семафоры после того, как предыдущий финиширует. Ваш случай немного похож ;)

Попробуйте что-нибудь подобное. Он должен игнорировать все попытки декремента времени, которые сталкиваются с обратным вызовом 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 работает как новый поток, и я бы ожидал, что браузеры сделают синхронизирующий доступ к памяти, так что может быть достаточно проверить, не выросло ли значение перед декрементом. Но вышеприведенное решение более гибкое и безопасное.

И один маленький совет - избегайте слишком частых запросов с AJAX - это может вызвать дополнительные проблемы - например, запросы, возвращающиеся в другом порядке, чем отправленные, и использование памяти Firefox, увеличивающееся на слишком большом количестве ajax в минуту ;)

.
-1
ответ дан 30 November 2019 в 22:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: