I have a javascript function where if loops are not following each other sequentially. I need them to run one after the other. The second loop should not run until the first loop has finished, because it deals with the output of the first.
I use an if loop (loop 1) to call a function in a child iframe (this frame contains mapping elements, and I can't reasonably combine it with the parent frame). This part is working as intended.
The function in the iframe is triggered, and it makes a call to an external service, and awaits a response. When it receives a response it passes either "error" or "ok" back to the parent function by using the 'return' function. This part is working as intended.
The parent receives the response, sets a variable and then should continue on with the next if statement (loop 2) that does something else.
What actually happens is that loop 1 runs, then loop 2 also runs, and loop 2 returns results before loop 1 - which screws things up as loop 2 is meant to be dealing with thee results from loop 1.
jQuery(document).on('click', '.gv-button-delete', function (e) {
e.preventDefault(); //prevent submission
console.log('Intercepted delete button request');
var delLoc = "";
(function ($) {
var delLoc2 = $('.gv-button-delete').attr("href"); //capture default action, because we need the time-valid nonce
delLoc = delLoc2;
}(jQuery));
var objID = document.getElementById("input_4_40").value;
objID = parseInt(objID);
var iframe = document.getElementById("MapFrame1");
var result = "";
if (iframe) { //1st if loop that collects the answer
var iframeContent = (iframe.contentWindow || iframe.contentDocument);
var result = iframeContent.WriteLog(objID); //call the function from the iframe, and hopefully wait for a result.
console.log(result);
}
if (result == "error") { //the second if loop
console.log("Step 5")
console.log("There was an error with removing the feature");
} else if (result == "ok") {
console.log("Step 5")
console.log("The spatial delete completed correctly");
} else {
console.log("Step 5")
console.log("unexpected result of spatial delete")
}
});
the iframe code, becuase it's useful for context.
function WriteLog(objID){
var retireFeatureID = hotspots.getFeature(objID);
var successStatus = "";
retireFeatureID.feature.properties["SystemStatus"] = "Deleted";
hotspots.updateFeature(retireFeatureID.feature, function (err, response) { //This is a syncronous call to another service
if (err) {
console.log("Step 3")
console.log(err);
successStatus = "error";
console.log("successStatus is: " + successStatus);
} else {
console.log("Step 3")
console.log(response);
successStatus = "ok";
console.log("successStatus is: " + successStatus);
}
});
console.log("Step 4")
console.log("Updated the status of feature: " + objID);
console.log("child iframe has variable successStatus as: " + successStatus);
return successStatus;
}
What actually happens is that the console results look like:
Step 4
Step 5
Step 3
The second loop is returning before the first loop has finished and returned a result.
This might be due to how callbacks and the javascript event loop work in general, and steps 4 and 5 will be executed first before step 3.
The function response callback will be placed at the end of call stack, which causes the remaining code (step 4 onwards and second if loop) to be executed without waiting for the callback to complete despite the other service code being synchronous.
I would suggest you to either convert the service function to one with a direct return and if possible not using callbacks, or changing the WriteLog
function to a callback function by adding a callback argument and invoking it once you get the response from the other service.