Как реализовать блокировку в JavaScript
как может что-то эквивалентно lock
в C# быть реализованы в JavaScript?
Итак, чтобы объяснить, что я думаю, простой случай использования:
пользователь нажимает кнопку B
. B
вызывает событие onclick. Если B
находится в event-state
событие ждет B
о ready-state
перед распространением. Если B
находится в ready-state
,B
заблокирован и имеет значение event-state
, то событие передается. Когда распространение события завершено, B
is установите значение ready-state
.
я мог видеть, как что-то близкое к этому может быть сделано, просто добавляя и удаляя класс ready-state
С помощью кнопки. Однако проблема заключается в том, что пользователь может нажать кнопку два раза подряд быстрее, чем переменная может быть установлена, поэтому эта попытка блокировки в некоторых обстоятельствах не удастся.
кто-нибудь знает, как реализовать блокировку, которая не подведет в JavaScript?
6 ответов:
блокировка-это сомнительная идея в JS, который предназначен для безрезьбового и не нуждающихся в защите параллелизма. Вы хотите объединить вызовы с отложенным выполнением. Шаблон, которому я следую для этого, - это использование обратных вызовов. Что-то вроде этого:
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.
JavaScript есть, причем очень мало исключения (
XMLHttpRequest
onreadystatechange
обработчики в некоторых версиях Firefox) параллельный цикл событий. Так что вам не нужно беспокоиться о блокировке в этом случае.JavaScript имеет модель параллелизма, основанную на"цикле событий". Эта модель отличается от модели на других языках, таких как C или Java.
...
среда выполнения JavaScript содержит очередь сообщений, которая является список сообщений для обработки. С каждым сообщением связана определенная функция. Когда стек пуст, сообщение извлекается из очереди и обработаны. обработка состоит из вызова соответствующей функции (и, таким образом, создания начального кадра стека) обработка сообщения заканчивается, когда стек снова становится пустым.
...
каждое сообщение обрабатывается полностью до обработки любого другого сообщения. благодаря свойства при рассуждении о вашей программе, включая тот факт, что всякий раз, когда функция запускается, она не может быть упреждена и будет выполняться полностью до запуска любого другого кода (и может изменять данные, которыми манипулирует функция). это отличается от C, например, где, если функция выполняется в потоке, она может быть остановлена в любой момент, чтобы запустить какой-либо другой код в другом потоке.
недостатком этой модели является то, что если сообщение занимает слишком много времени для завершения, веб-приложение не удается обработать пользовательские взаимодействия, такие как щелчок или прокрутка. Браузер смягчает это с помощью диалогового окна "сценарий занимает слишком много времени для запуска". хорошая практика заключается в том, чтобы сделать обработку сообщений короткой и, если это возможно, сократить одно сообщение на несколько сообщений.
дополнительные ссылки на параллелизм цикла событий см. В разделе E
замки-это концепция, необходимая в многопоточной системе. Даже с рабочими потоками сообщения отправляются по значению между рабочими, так что блокировка не требуется.
Я подозреваю, что вам нужно просто установить семафор (система маркировки) между вашими кнопками.
У меня был успех мьютекс-обещание.
Я согласен с другими ответами, что вам может не понадобиться блокировка в вашем случае. Но это неправда, что никогда не нужно блокировать в Javascript. Вам нужна взаимная исключительность при доступе к внешним ресурсам, которые не обрабатывают параллелизм.
почему бы вам не отключить кнопку и включить его после завершения мероприятия?
<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>
удачи в кодировании !!!
некоторое дополнение к ответу Джошрайвера в соответствии с моим случаем;
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, и эти две функции будут потреблять один и тот же результат.