атомарная операция нарушена асинхронными обратными вызовами ajax

Я знаю, использование слов JavaScript и «атомарный» в одном предложении выглядит довольно странно, поскольку JavaScript считается асинхронным и, следовательно, не очень атомарным.

// РЕДАКТИРОВАТЬ Это была ошибка с моей стороны! из-за срабатывания предупреждения (и скрытия дальнейших предупреждений в хроме) оно быстро прервалось и позволило летать другому коду. JavaScript является однопоточным.

Quick -> Actual Question; в какой ситуации мы спасаемся от асинхронных прерываний обратного вызова и как мы можем предотвратить их для определенных блоков кода?

Long -> My Scenario; Все мое приложение очень рекурсивно и запускает много запросов ajax, которые при возврате запускают еще много рекурсивных функций, которые могут запускать больше запросов ajax. В моем коде у меня есть несколько очень важных операций с массивом, которые должны быть завершены до того, как может произойти следующая операция (однако простая логика push/splice).

У меня была проблема, когда я получил индекс ключа в массиве и сохранил его в переменной. Затем я сравнил его с -1, и если это было так, я соединил (а не просто удалил) элемент из массива. Теперь, между получением индекса и объединением, асинхронный обратный вызов возвращал результаты и запускал рекурсивные действия, которые затем изменяли массив, добавляя/удаляя дополнительные элементы (и искажая значение индекса, которое я получил ранее).

Это был старый код;

if ( this.dataset && (index=this.dataset.children.indexOf(child.key) )!==-1 ){
    console.log("removed from dataset!");
    //<=== AJAX Call Returns and adds/removes items from the array
    this.dataset.children.splice(index, 1); //goes bad, because index not good anymore
    ...
}

и это "рабочий", но не оптимизированный код

if ( this.dataset && (index=this.dataset.children.indexOf(child.key) )!==-1 ){
    console.log("removed from dataset!");  
    //<=== AJAX Call Returns and adds/removes items from the array
    //Problem solved, since I'm getting the index again
    this.dataset.children.splice(this.dataset.children.indexOf(child.key), 1);
    ...
}

Я просто снова ищу индекс и напрямую соединяю его.

мой общий вопрос: в какой ситуации мы спасаемся от асинхронных прерываний обратного вызова и как мы можем предотвратить их для определенных блоков кода?

Мой конкретный вопрос, товарищи StackOverflowers, заключается в том, может ли теоретически обратный вызов ajax быть вызван между функцией indexOf, возвращающей индекс, и функцией соединения, разрезающей массив.

Спасибо за помощь

p.S. Я знаю, что я просто могу отключить поле массива, и моя проблема с индексом будет решена. Но это не то, что я хочу, так как я сериализую эту информацию и не хочу сотых пустых записей. Моя цель - найти общий способ решения таких ситуаций :)


person japrescott    schedule 30.11.2011    source источник


Ответы (2)


JavaScript по своей сути является однопоточным. Это означает, что если приходит ответ AJAX или должен быть активирован тайм-аут/интервал, но выполняется другой код, обратный вызов/тайм-аут ответа будет ожидать.

Это была одна из основных причин, по которой JavaScript был выбран для node.js.

Смотрите также:

person Tomasz Nurkiewicz    schedule 30.11.2011
comment
Спасибо! Я только что так сильно фейспалмил, после того как понял, что между ними срабатывали предупреждения, что вызывало срабатывание обратных вызовов. - person japrescott; 01.12.2011

Javascript полностью однопоточный.

Асинхронные обратные вызовы могут выполняться только тогда, когда никакой другой код не выполняется с использованием очереди сообщений, например сообщений Windows.
Весь код выполняется в потоке пользовательского интерфейса, и ваш код никогда не может быть прерван в середине (за исключением предупреждение о неотвечающем сценарии)

Обратите внимание, что Javascript поддерживает настоящую многопоточность с использованием HTML5 Web Workers.

person SLaks    schedule 30.11.2011
comment
Есть причина, по которой никто не говорит о потокобезопасности Javascript. - person SLaks; 01.12.2011