Here is what I would like to do: first, separate code in the functions, this will simplify the work.
startCall should initiate your call, it receives callURL, which ajax should use. It returns a promise that will be resolved after its creation.
monitorCall accepts the callID, and a callback (the third parameter, "failed_tries" is used internally.) It will run a status check with ajax and call itself every 5 seconds until either 5 consecutive failures occur, or until we get the correct state of things. The callback is a regular JS callback with an error and the result as arguments.
getMonitoredCall will join the previous two functions together to make a promise that will be resolved after the call is completed.
getNewCallUrl is used to provide another call. This function will be called before each call to receive a call for the call. There is work for you! It should return a promise that gives the URL as a result.
Finally, loopCalls initiates everything, and as soon as the call is completed, it will call itself again to continue the next call until something works.
function startCall(callURL){ return $.ajax({ url: callURL, data: {}, type: "GET" }).then(function(data, status, xhr) { var httpStatus = status; var httpResponseCode = (xhr.status); var httpResponseText = (xhr.responseText); $('#ajaxSuccessBulk').html('Call in Progress').show(); $("#startBulkContactCall").prop("disabled", true); $("#callNextBulkContact").prop("disabled", true); return Promise.resolve(xhr.responseText.match(/ActionID = (.+)/)[1]); }) .fail(function(xhr) { var httpStatus = (xhr.status); var httpResponseCode = (xhr.getAllResponseHeaders); var httpResponseText = (xhr.responseText); var ajaxError = 'There was an error requesting the call back. HTTP Status: ' + httpStatus + ' ' + httpResponseText; //make alert visible $('#ajaxError').html(ajaxError).show(); }); } function monitorCall(callID,callback,failed_tries){ failed_tries = failed_tries || 0; $.ajax({ url: 'https://www.acme.com/GetStatus.php', data: {ActionID:callID}, type: "GET" }).then(function(data){ if(data && data.split(',')[2] != "IN_PROGRESS"){ callback(null,data); }else{ setTimeout(monitorCall.bind(null,callID,callback,0),5000); } }).fail(function(xhr){ failed_tries++; if(failed_tries>5){ callback("Error trying to get the status, stopping after 5 consecutive tries."); }else{ setTimeout(monitorCall.bind(null,callID,callback,failed_tries),5000); } }); } function getMonitoredCall(callUrl){ return new Promise(function(resolve,reject){ startCall(callUrl).then(function(callID){ monitorCall(callID,function(err,res){ if(err){ reject(err); }else{ resolve(res); } }); }); }); } function getNewCallUrl(){ return $.ajax({ url: "http://getNewCallUrl/", data: {}, type: "GET" }).then(function(data, status, xhr) { //Let presume the request simply returns a call URL. return Promise.resolve(data); }) .fail(function(xhr) { var httpStatus = (xhr.status); var httpResponseCode = (xhr.getAllResponseHeaders); var httpResponseText = (xhr.responseText); var ajaxError = 'There was an error requesting the call back. HTTP Status: ' + httpStatus + ' ' + httpResponseText; //make alert visible $('#ajaxError').html(ajaxError).show(); }); } function loopCalls(){ getNewCallUrl().then(function(callUrl){ return getMonitoredCall(callUrl); }).then(function(){setTimeout(loopCalls,5000)}); } loopCalls();