Как реализовать блокировку в JavaScript

Как может быть реализовано что-то эквивалентное lock в С# в JavaScript?

Итак, чтобы объяснить, что я думаю, простой пример использования:

Пользователь нажимает кнопку B. B вызывает событие onclick. Если B находится в event-state, событие ожидает, что B будет находиться в ready-state до распространения. Если B находится в ready-state, B заблокирован и имеет значение event-state, тогда событие распространяется. Когда распространение события завершено, B устанавливается на ready-state.

Я мог видеть, как можно сделать что-то близкое к этому, просто добавив и удалив класс ready-state с помощью кнопки. Однако проблема заключается в том, что пользователь может дважды щелкнуть кнопку в строке быстрее, чем может быть задана переменная, поэтому при некоторых обстоятельствах эта попытка блокировки не удастся.

Кто-нибудь знает, как реализовать блокировку, которая не будет работать в JavaScript?

Ответ 1

Блокировка является сомнительной идеей в JS, которая предназначена для обеспечения безотказной работы и не нуждается в защите concurrency. Вы хотите комбинировать вызовы с отложенным исполнением. Образец, который я придерживаюсь для этого, - это использование обратных вызовов. Что-то вроде этого:

var functionLock = false;
var functionCallbacks = [];
var lockingFunction = function (callback) {
    if (functionLock) {
        functionCallbacks.push(callback);
    } else {
        $.longRunning(function(response) {
             while(functionCallbacks.length){
                 var thisCallback = functionCallbacks.pop();
                 thisCallback(response);
             }
        });
    }
}

Вы также можете реализовать это с помощью прослушивателей событий DOM или решения pubsub.

Ответ 2

JavaScript содержит очень мало исключений (XMLHttpRequest onreadystatechange обработчиков в некоторых версиях Firefox) event-loop concurrent. Поэтому вам не нужно беспокоиться о блокировке в этом случае.

JavaScript имеет модель concurrency, основанную на "цикле событий". Эта модель сильно отличается от модели на других языках, таких как C или Java.

...

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

...

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

Недостатком этой модели является то, что если сообщение занимает слишком много времени, веб-приложение не может обрабатывать взаимодействия пользователя, такие как щелчок или прокрутка. Браузер смягчает это с помощью диалога "a script занимает слишком много времени". Хорошая практика заключается в том, чтобы сделать обработку сообщений короткими и, если возможно, сократить одно сообщение на несколько сообщений.

Дополнительные ссылки на event-loop concurrency см. E

Ответ 3

Замки - это концепция, требуемая в многопоточной системе. Даже с рабочими потоками сообщения отправляются по значению между рабочими, поэтому блокировка не нужна.

Я подозреваю, что вам нужно просто установить семафор (систему маркировки) между вашими кнопками.

Ответ 4

Почему бы вам не отключить кнопку и включить ее после завершения события?

<input type="button" id="xx" onclick="checkEnableSubmit('true');yourFunction();">

<script type="text/javascript">

function checkEnableSubmit(status) {  
  document.getElementById("xx").disabled = status;
}

function yourFunction(){

//add your functionality

checkEnableSubmit('false');
}

</script>

Счастливое кодирование!!!

Ответ 5

У меня был успех mutex-promise.

Я согласен с другими ответами, что вам может не понадобиться блокировка в вашем случае. Но это не так, что никогда не нужно блокировать Javascript. Вам нужна взаимная эксклюзивность при доступе к внешним ресурсам, которые не обрабатывают concurrency.

Ответ 6

Некоторое дополнение к JoshRiver отвечает в соответствии с моим случаем;

var functionCallbacks = [];
    var functionLock = false;
    var getData = function (url, callback) {
                   if (functionLock) {
                        functionCallbacks.push(callback);
                   } else {
                       functionLock = true;
                       functionCallbacks.push(callback);
                        $.getJSON(url, function (data) {
                            while (functionCallbacks.length) {
                                var thisCallback = functionCallbacks.pop();
                                thisCallback(data);
                            }
                            functionLock = false;
                        });
                    }
                };

// Usage
getData("api/orders",function(data){
    barChart(data);
});
getData("api/orders",function(data){
  lineChart(data);
});

Будет только один вызов api, и эти две функции будут использовать тот же результат.