Question

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?

Was it helpful?

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
});

OTHER TIPS

the problem may be related to the scope of your w variable, because on second call (in the wait function, into your else branch) you're destroying the reference to the timeout you previously created, so the clearTimeout can't work: try to define it in the immediate outer scope.

You should try using the JavaScript setInterval function instead of setTimeout. But this time, break up sendMessage, and place the part that needs to execute after the ajax message is received under a setInterval.

Once the ajax message is received this second part of sendMessage runs (after messagereceived is true), and also clears the interval.

This is since setTimeout() only executes once after a set interval.

setInterval() executes repeatedly exery interval until it is cleared.

More information can be found Here

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top