«атомарная» операция, нарушенная асинхронными обратными вызовами ajax - PullRequest
2 голосов
/ 01 декабря 2011

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

// EDIT Это была ошибка на моей стороне! отключив оповещение (и скрыв дальнейшие оповещения в chrome), он быстро прерывается и позволяет другому коду летать. JavaScript является однопоточным.

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

Long -> Мой сценарий; Все мое приложение очень рекурсивно и запускает много запросов 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 Я знаю, что я мог бы просто сбросить поле массива, и моя проблема с индексом была бы решена. Но это не то, что я хочу, так как я сериализую эту информацию и не хочу сотых пустых записей. Моя общая цель - найти общий способ решения таких ситуаций:)

Ответы [ 2 ]

7 голосов
/ 01 декабря 2011

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

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

См. также:

2 голосов
/ 01 декабря 2011

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

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

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

...