Семафор Javascript / тест-и-набор / блокировка? - PullRequest
47 голосов
/ 17 февраля 2009

Есть ли такая вещь, как атомарный тест и набор, семафор или блокировка в Javascript?

У меня есть JavaScript, вызывающий асинхронные фоновые процессы через пользовательский протокол (фоновый процесс буквально выполняется в отдельном процессе, не связанном с браузером). Я полагаю, что я нахожусь в состоянии гонки; фоновый процесс возвращается между моим тестом и моим сетом, что портит все на стороне JavaScript. Мне нужна операция test-and-set, чтобы сделать ее настоящим семафором.

Вот код JavaScript, который пытается обнаружить фоновые процессы и поставить их в очередь:

Call = function () {

var isRunning = true,
    queue = [];

return  {
    // myPublicProperty: "something",

    call: function (method) {
            if (isRunning) {
                console.log("Busy, pushing " + method);
                queue.push(method);
            } else {
                isRunning = true;
                objccall(method);
            }
        },

        done: function() {
            isRunning = false;
            if (queue.length > 0) {
                Call.call(queue.shift());
            }
        }
    };
}();

Call - это синглтон, который реализует очередь; любой, кто хочет вызвать внешний процесс, делает Call.call («что-то»).

Есть идеи?

Ответы [ 5 ]

21 голосов
/ 17 февраля 2009

JavaScript не имеет семантики блокировки, поскольку JS не является многопоточным языком. Несколько потоков могут работать одновременно только в совершенно разных контекстах, например. Рабочие потоки HTML5 или такие вещи, как множественные экземпляры объекта контекста API JavaScriptCore (я предполагаю, что SpiderMonkey имеет похожую концепцию). У них не может быть общего состояния, поэтому по сути все выполнение является атомарным.

Хорошо, поскольку вы сейчас предоставили часть своего кода, я предполагаю, что у вас есть что-то похожее на:

External Process:
<JSObject>.isRunning = true;
doSomething()
<JSObject>.done()

Или некоторые такие (с использованием соответствующих API). В этом случае я ожидал бы, что механизм JS будет блокироваться, если JS выполняется в контексте вашего объекта js (что и делает JavaScriptCore), в противном случае вам, вероятно, потребуется установить ручную блокировку вокруг выполнения js.

Какой движок вы используете для всего этого? Я спрашиваю, потому что, исходя из вашего описания, звучит так, как будто вы устанавливаете флаг из вторичного потока из языка, отличного от JS, с помощью API C / C ++, предоставляемого этим языком, и большинство механизмов JS предполагают, что любая манипуляция состоянием выполняется через API будет происходить в одном потоке, обычно в том же потоке, в котором выполняется все выполнение.

2 голосов
/ 17 февраля 2009

Может быть, вы могли бы реализовать базовый целочисленный семафор, просто добавьте переменную в DOM и заблокируйте / разблокируйте ее и убедитесь, что ваши функции продолжают проверять ее, в противном случае время ожидания их =)

Если вы используете фреймворк, такой как Mootools, вы можете попытаться обработать поток приложения с помощью таких событий, как onComplete и т. Д.

1 голос
/ 15 января 2017

Я не совсем уверен, что именно задает вопрос, но посмотрите мой объект семафора здесь: https://github.com/agamemnus/semaphore.js.

1 голос
/ 04 октября 2015

Прежде всего, хотя это правда, что javaScript является однопоточным, это НЕ правда, что приложение javaScript никогда не требует механизма сериализации.

Простой пример, когда кнопка отправки должна исчезать в течение заданного промежутка времени, в течение которого работает Ajax-запрос к серверу. Когда асинхронный Ajax-запрос успешно завершается, должно появиться сообщение о том, где раньше находилась кнопка.

Хотя было бы неплохо иметь возможность отменить затухание кнопки и просто установить ее стиль на «display: none», как только запрос Ajax завершится, это невозможно в jQuery. Кроме того, решение могло бы использовать События для синхронизации двух одновременных действий, но это по существу излишне для простой проблемы.

Низкотехнологичное решение состоит в том, чтобы опросить блокировку, и когда затухание завершается, она разблокируется, но сообщение «сервер завершен» НЕ отображается до тех пор, пока не будет выполнен обратный вызов успеха, заданный $ .post.

var gl_lock;
var gl_selfID;

function poll_lock(message) {
     if (gl_lock === 0) {
          $('#output').text(message).fadeIn(200);
          window.clearInterval(gl_selfID);
     }
 } // end of poll_lock

 function worker() {

     // no one gets in or out
     gl_lock = 1;

     $.post(..., data,function() { 
           gl_selfID = window.setInterval(poll_lock, 40, data.message);
      }, "json");

     // end of fadeout unlock the semaphore
     $('#submit-button').fadeOut(400, function() { gl_lock = 0; });

  } // end of worker

Наконец, я думаю, что это более подробный ответ, в соответствии с ранее предложенным perrohunter в этом обсуждении.

0 голосов
/ 09 июня 2014

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

var semaphore=[];

function myFunc(arg){
   var dfd;
   $.when(semaphore[table]).done(
      function(){
            dfd=myFuncInner(arg);
      }
      );
return dfd;
}

function myFuncInner(table){
semaphore[arg] = new $.Deferred();
... 
somethingasynchronous({
    semaphore[arg].resolve();
});

return  semaphore[arg];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...