Search code examples
javascriptjquerywaitmodule-pattern

Javascript Module Pattern and jquery Ajax wait issue


I have written a custom js module that basically sends messages and needs to wait for a response in order to continue:

var manageBooking = (function (jQ) {

//decalre private variables
var domain, msgRecieved, msgResponse, validationValue;
//decalre private functions
var sendMessage, wait;

// A private variables
domain = document.domain;
msgRecieved = false;
msgResponse = null;


wait = function(timeOutStep){
    var w;
    console.log('msgRecieved', msgRecieved);
    if (msgRecieved === true) {
        clearTimeout(w);
        return;
    } else {
        console.log('waiting..');
        w = setTimeout(wait, timeOutStep, timeOutStep);
    }
}

// A private function to send messages
sendMessage = function( requestURL, data, type ) {
    console.log(requestURL);
    console.log(data);
    console.log(type);
    //reset vars to defaults
    msgRecieved = false;
    msgResponse = null;
    jQuery.ajax({
        url: "http://"+domain+"/_ajax/"+requestURL,
        dataType: "html",
        async: true,
        data: data,
        type: type,
        success: function(msg){
            console.log(msg);
            msgResponse = msg;
            msgRecieved = true;
        }
    });
    console.log('after ajax call');
    wait(500);
    console.log('after wait');
    console.log('msgRecieved', msgRecieved);
    return;
};
return {

// A public variable
errorMsg: "",
validationName: "",
bookingID: "",
output: "",
// A public function to login
login: function( enteredBookingID, enteredSurname ) {
    // Call private sendMsg
    sendMessage("user_login/"+enteredBookingID+"/"+enteredSurname, null, 'GET');
    console.log(msgResponse);
    throw "error";
    //check response
    var patt=/Sorry/i;
    //test pattern
    var result=patt.test($.trim(msgResponse));
    //if false OK
    if (result === false) {
        var split = msgResponse.split('|');
        validationName = split[0];
        validationValue = split[1];
        bookingID = enteredBookingID
        return true;
    }
    //else error
    errorMsg = msgResponse;
    return false;
}
};
})(jQuery);
manageBooking.login(123,123);

The issue i am having is forcing the sendMessage function to wait until the ajax completes and sets msgRecieved to true.

However it appears that the sendMessage function hits the wait function once and then continues. the following console output shows the order of events:

GET http://website/_ajax/user_login/123/123
after ajax call //sendMessage()
msgRecieved, false //wait()
waiting.. //wait()
after wait //sendMessage()
msgRecieved, false //sendMessage()
null//login()
uncaught exception: error //login() 
<p>Sorry, we cannot locate your details.  </p> <!-- jQuery Ajax call -->
msgRecieved, true //wait()

What I am confused with is that the wait function seems to fire again right at the end..

can anyone give me some pointers on getting this to work?


Solution

  • JavaScript behaves in an asynchronous manner, meaning it does not wait.

    You have a part in your code that looks like this:

    jQuery.ajax({
        url: "http://"+domain+"/_ajax/"+requestURL,
        dataType: "html",
        async: true,
        data: data,
        type: type,
        success: function(msg){
            console.log(msg);
            msgResponse = msg;
            msgRecieved = true;
        }
    });
    

    You should place the code to be run when the response arrives within the success function, like so:

    success : function (msg) {
        handleMessage(msg); // Or any other manipulation to the received message
    }
    
    function handleMessage(msg) {
        // Work with your received message here.
    }
    

    success will be called with the received message, it is a callback.

    The right way to implement sendMessage would be the following way:

    sendMessage = function( requestURL, data, type, callback ) {
        console.log(requestURL);
        console.log(data);
        console.log(type);
        //reset vars to defaults
        msgRecieved = false;
        msgResponse = null;
        jQuery.ajax({
            url: "http://"+domain+"/_ajax/"+requestURL,
            dataType: "html",
            async: true,
            data: data,
            type: type,
            success: function(msg){
                console.log(msg);
                msgResponse = msg;
                msgRecieved = true;
                // Call the callback function to notify the message
                // was received
                callback();
            }
        });
    };
    

    and then using it like so:

    sendMessage(urlHere, dataHere, typeHere, function () {
        // Message has been received, msgResponse and msgReceived
        // have already been updated. Do what you need here
    });