Javascript semaphore / test-and-set / lock?

前端 未结 6 797
无人共我
无人共我 2020-12-13 23:09

Is there such a thing as an atomic test-and-set, semaphore, or lock in Javascript?

I have javascript invoking async background processes via a custom protocol (the b

相关标签:
6条回答
  • 2020-12-13 23:37

    Maybe you could implement a basic integer semaphore, just add the variable into the DOM and lock/unlock it and make sure your functions keep checking it, else timeout them =)

    If you are using a framework such as Mootools you could try to handle the flow of the app with events such as onComplete and so on.

    0 讨论(0)
  • 2020-12-13 23:38

    JavaScript has no locking semantics because JS is not a multi threaded language. Multiple threads can only operate concurrently in completely distinct contexts -- eg. HTML5 Worker threads, or in things like multiple instances of JavaScriptCore API's context object (I assume SpiderMonkey has a similar concept). They can't have shared state, so in essence all execution is atomic.

    Okay, as you have now provided some of your code i assume you have something akin to:

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

    Or some such (using appropriate APIs). In which case I would expect the JS engine to block if JS is executing in the context of your js object (which is what JavaScriptCore would do), failing that you will probably need to put a manual lock in place around js execution.

    What engine are you using to do all of this? I ask because based on your description it sounds like you're setting a flag from a secondary thread from a non-JS language using the C/C++ API provided by that language, and most JS engines assume that any state manipulation made via the API will be occurring on a single thread, typically the same thread that all execution occurs on.

    0 讨论(0)
  • 2020-12-13 23:49

    I had the same issue, here is how I solved it. It works fine for two concurrent processes. If you have three processes or more, it is possible that two processes start together.

    var isRunning = false;
    ...
    var id = setInterval(function(){ //loop until isRunning becomes false
                if (!isRunning){
                    isRunning = true;
                    //do something synchronous or use a promise
                    isRunning = false;
                    clearInterval(id); // stop the loop here
                }
            , 10);
    

    It is better than the while loop because it solves concurrency/async issues for reading/setting isRunning.

    0 讨论(0)
  • 2020-12-13 23:52

    First of all, while it is true that javaScript is single threaded, it is NOT true that no serialization mechanism is ever required by a javaScript application.

    A simple example, is when a submit button should fade out for a set amount of time during which an Ajax request to a server is working. When the asynchronous Ajax request successfully completes then a message should appear where the button used to be.

    While it would be nice to be able to cancel the button's fadeout and simply set its style to "display: none", as soon as the Ajax request completes, that is not possible in jQuery. Also, a solution could use Events to synchronize the two simultaneous activities, but that is essentially overkill for a simple problem.

    A low-tech solution is to poll a lock and when the fadeout completes it is unlocked but the "server done" message is NOT displayed until the success callback, as set by $.post, executes.

    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
    

    Finally, I think this is more detailed answer, along the lines previously suggested in this discussion by perrohunter.

    0 讨论(0)
  • 2020-12-13 23:58

    I'm not really sure what the question is asking exactly, but check out my semaphore object here: https://github.com/agamemnus/semaphore.js.

    0 讨论(0)
  • 2020-12-13 23:58

    I have ajax stuff which populates select lists, I needed it to be locked so I did something like this. I think you could probably do it simpler though using deferreds and pipes or something.

    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];
    }
    
    0 讨论(0)
提交回复
热议问题