Cornwell
Cornwell

Reputation: 3410

mutex_lock equivalent in javascript

I have an ajax function that will post data and then show a message with OK\Problem

$.ajax({
            url: 'save.php',
            type: "POST",
            data: jsObj
            //contentType: "application/json"
        })
      .success(function (result)
      {

      var status = result.split(";")[0];
      var msg = result.split(";")[1];
      if ((status == "Ok") && ($('#divMsg').css('display') == 'none'))
      {
          //console.log($('#divMsg').css('display'));
          $("#divMsg").toggle("slow");
          $("#divMsg").find("p").text("Saved");
      }
       (...)

The problem is that it might get called several times in a second, so it will show a div saying saved multiple times. I just want it to show one time. I tried checking if the div was hidden, but it must happen too fast and it still shows as visible for the next messages.

Is there any way I could get some locking mechanism?

Upvotes: 0

Views: 127

Answers (3)

slashingweapon
slashingweapon

Reputation: 11307

Javascript in the client is single-threaded, unless you explicitly create worker tasks (and not all browsers support that). You probably want to keep a variable somewhere that tracks the number of outstanding requests, and only print a result when the last request completes.

Keeping the counter in your output element is a decent idea, but it should be a counter and not just a true/false flag. I'm assuming that you might want to process multiple requests at a time, and only show the result once the last request has been resolved.

// save the divMsg element, since we're going to use it a few times.
var divMsg = $("#divMsg");
var count = divMsg.data('pendingRequests');
divMsg.data('pendingRequests', count ? count+1 : 1); // increment the count, or set it to 1

$.ajax({
    url: 'save.php',
    type: "POST",
    data: jsObj
}).done(function (result) {
    var status = result.split(";")[0];
    var msg = result.split(";")[1];
    if ((status == "Ok") && (divMsg.css('display') == 'none')) {
        // if this is the last request, print the status
        if (divMsg.data('pendingRequests') == 1)
            divMsg.toggle("slow").find("p").text("Saved");
    }
    (... etc ...)
}).always( function(result) {
    // decrement the pending request count.
    var count = divMsg.data('pendingRequests');
    divMsg.data('pendingRequests', count-1);
});

You could add a fail() handler too, and print failure information.

Upvotes: 2

j_mcnally
j_mcnally

Reputation: 6968

I would suggest using a real data store if thats the case.

Ember and ExtJs both have examples of this, but there may be standalones, generally records are wrapped in an object that stores state, like isLoaded, isDirty etc, which could be used for pseudo-locking a record, or implement it yourself via a object wrapper.

Also If data resolution is a goal check out

https://github.com/ebryn/bigdata.js

Upvotes: 0

DhruvPathak
DhruvPathak

Reputation: 43245

Just use a javascript object and sets its keys to true or false as per the lock you want.

    var locks = {};


    var functionWithMutex = function(){
     if(locks['state_name'] == true){
           return;
      }
     locks['state_name'] = true;
     ....do some task...then release the lock by setting to false.
};

Upvotes: 0

Related Questions