AJAX trigger remote script then check for success-response - javascript

I've been searching my brains out but I can't seem to wrap my head around the little help I find.
I'm running a database that is being fed by data from another DB. The csv transport is handled by a third party server providing executable "flows" which compile and deliver the data.
I have a php script to handle the request (can't be done directly via Javascript because of the missing 'Access-Control-Allow-Origin' header). But this runs nicely. I can trigger the flow.
This is not the problem though.
What I want to do: trigger the flow #onClick of a button with something like this:
function trigger_func(flowID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID,
dataType: 'json',
success: function(result) {
var jsonResult = jQuery.parseJSON(result);
console.log(jsonResult.runID);
}
});
}
With the flowID and the resulting runID I want to check back like every second or so.
function check_status(flowID, runID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID+"&action=status&runId="+runID,
dataType: 'json',
success: function(result){...}
});
}
This will return the status / progress of the flow.
It will start for a few seconds with status==null, then go on to status=='running' and finally status=='success'.
I have gotten check_status() to run for i.e. 15 times with a setTimeout in a for loop within the success-function of trigger_func() and it works fine too.
But I cannot for the life of me figure out how I would link this stuff together to have it checking until status is 'success' and then stop checking, update page content and so on...
I have also fiddled with something like
trigger_func(id).done(function(result){
console.log(result);
});
This works too but still I can't think my way further to the checking every second until 'success'. I guess it comes down to getting the variable 'status' back into my loop so I can break it.
Maybe someone knows of a comprehensible example somewhere online...

You could do this:
function periodically_check_status_until_success(flowID, runID) {
setTimeout(function() {
$.ajax({
url: './ajaxPHP_handler.php',
data: { flowid: flowID, action: status, runId: runID },
dataType: 'json',
success: function(result){
if (result != 'success') {
periodically_check_status_until_success(flowID, runID);
}
}
});
}, 5000); // Five seconds
}
Note: You can use an object for the data option, rather than concatenate the string yourself.

So just keep calling it
var flowID, runID;
function trigger_func(flowID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID,
dataType: 'json',
success: function(result) {
var jsonResult = jQuery.parseJSON(result);
runID= jsonResult.runID;
check_status();
}
});
}
function check_status() {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID+"&action=status&runId="+runID,
dataType: 'json',
success: function(result){
if (result is not what you want) {
setTimeout(check_status,1000);
}
}
});
}

ajax are async so you have to manage by this via some 3rd party variable
Like Init with value 0
var _status = 0
than change it on your first call set it 1
function trigger_func(flowID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID,
dataType: 'json',
success: function(result) {
var jsonResult = jQuery.parseJSON(result);
console.log(jsonResult.runID);
check_status(flowID, runID);
}
});
}
function check_status(flowID, runID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID+"&action=status&runId="+runID,
dataType: 'json',
success: function(result){
//at end status=='success'.
if(status=='success'){
// end part
}else{// running
check_status(flowID, runID);
}
// clear timeout will stop that time interval after success
}
});
}

Related

AJAX request sometimes out of order

I'm having trouble with POST and GET request. On my server side right up until the moment before I send I have what I expect but then on my client side I get things out of order. For example these two should be in the reverse order I have here:
Sending from server{"grid":["","","","","","","","",""],"winner":""}
Received at server: {"grid":["X","","","","","","","",""],"winner":""}
function sendData(json) {
$.ajax({
type: "POST",
url: "/ttt",
data: json,
dataType: "json",
success: receiveData()
});
}
function receiveData() {
var response = $.ajax({
type: "GET",
url: "/ttt",
dataType: "json",
success: function(){
grid = response.responseJSON;
console.log("Receved at client: " + JSON.stringify(grid));
}
});
console.log("Also after receiving " + JSON.stringify(grid));
}
gives me:
Also after receiving {"grid":["X","","","","","","","",""],"winner":""}
Receved at client: {"grid":["X","O","","","","","","",""],"winner":""}
I think this may two different problems. One for getting things out of order and another for why my grid doesnt reflect the changes after my success clause function in my GET request.
You're making a common mistake. You need to use a function reference without the parens here for receiveData. Change this:
function sendData(json) {
$.ajax({
type: "POST",
url: "/ttt",
data: json,
dataType: "json",
success: receiveData()
});
}
to this:
function sendData(json) {
$.ajax({
type: "POST",
url: "/ttt",
data: json,
dataType: "json",
success: receiveData // no parens here
});
}
When you include the parens, it calls the function IMMEDIATELY and puts the return value from the function as the success handler and thus you see them run out of order. You want to pass a function reference to it can be called later. A function reference is the function's name without the parens.
It also appears like you have another mistake in receiveData(). You are using the wrong thing for the response. The response is not returns from $.ajax(). The response is passed to the success handler.
I don't know exactly what your response is supposed to look like, but change this:
function receiveData() {
var response = $.ajax({
type: "GET",
url: "/ttt",
dataType: "json",
success: function(){
grid = response.responseJSON;
console.log("Receved at client: " + JSON.stringify(grid));
}
});
console.log("Also after receiving " + JSON.stringify(grid));
}
to something like this:
function receiveData() {
$.ajax({
type: "GET",
url: "/ttt",
dataType: "json",
success: function(response){
grid = response.responseJSON;
console.log("Received at client: " + JSON.stringify(grid));
console.log("Also after receiving " + JSON.stringify(grid));
}
});
}
And, because your ajax calls are asynchronous, you also had this statement console.log("Also after receiving " + JSON.stringify(grid)); in the wrong place. If you want to see the results of the grid after you've modified it, then you have to put that inside the success handler.
Summary of Fixes
Change success: receiveData() to success: receiveData.
Use response as it is passed to the success handler.
Put console.log() to see final results inside the success handler.
It appears that you may not fully understand how ajax calls are asynchronous and what that really means for your programming. I'd suggest doing some searching and reading on that topic. Learning that now will save you a lot of agony as you develop.

updated UI not showing before sync ajax call

I Have a 2 JavaScript functions what call one after another. like following.
updateUI(event);
syncCall();
function updateUI(event) {
formSubmitBtn = $(event.target).find('[type=submit]:not(".disabled")');
formSubmitBtn.attr('disabled', 'disabled');
var loadingText = I18n.t('Submitting');
formSubmitBtn.val(loadingText).text(loadingText);
}
function syncCall(){
$.ajax({
async: false,
dataType: 'json',
type: 'GET',
url: '/calls/synccall',
success: function (json) {
userIsSignedIn = json.is_signed_in;
}
});
}
I am updating a UI element before sync ajax call. but UI changes are not showing. When I try to debug the code it works fine.
I can imagine your code is doing something like
var userIsSignedIn;
updateUI(event);
syncCall();
nextThing(userIsSignedIn);
anotherThing();
moreThings();
With a simple change to syncCall - called asyncCall to be not confusing
function asyncCall(cb){
$.ajax({
dataType: 'json',
type: 'GET',
url: '/calls/synccall',
success: function (json) {
cb(json.is_signed_in);
}
});
}
your code re-written:
updateUI(event);
asyncCall(function(userIsSignedIn) {
nextThing(userIsSignedIn);
anotherThing();
moreThings();
});
Note the lack of var userIsSignedIn; required
Really a small change for improved end user experience
a second alternative is to wrap all the code you presented in a function tagged async
async function doThings() {
updateUI(event);
let userIsSignedIn = await ajaxCall(); // see below
nextThing(userIsSignedIn);
anotherThing();
moreThings();
}
and return a Promise from ajaxCall (what was syncCall)
function ajaxCall(){
return $.ajax({
dataType: 'json',
type: 'GET',
url: '/calls/synccall'
}).then(json => json.is_signed_in);
}
Run this through a transpiler (like babel) to produce code that should work on Internet Exploder and similarly "backward" browsers
Summary: In the end you have two choices
Use async:false and have rubbish user experience
embrace asynchrony and write code that befits the 21st century
Call this function beforeSend like as follows
function syncCall(){
$.ajax({
async: false,
dataType: 'json',
type: 'GET',
url: '/calls/synccall',
beforeSend:function(){
updateUI(event);// Call here
}
success: function (json) {
userIsSignedIn = json.is_signed_in;
}
});
}
If above not work try following
updateUI(event);
function updateUI(event) {
formSubmitBtn = $(event.target).find('[type=submit]:not(".disabled")');
formSubmitBtn.attr('disabled', 'disabled');
var loadingText = I18n.t('Submitting');
formSubmitBtn.val(loadingText).text(loadingText);
syncCall();// Try calling here
}
function syncCall(){
$.ajax({
async: false,
dataType: 'json',
type: 'GET',
url: '/calls/synccall',
success: function (json) {
userIsSignedIn = json.is_signed_in;
}
});
}

How to pass a variable from ajax to nested ajax

I'm sending ajax call and getting an answer that I need from the first ajax then I want to pass my result to my nested ajax, my var (result) is null in the nested ajax/settimeout fun, can I pass it ? Am I missing something ?
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
contentType:'json' ,
dataType:'text',
success: function (result) {
alert(result);**-> is fine - not null**.
// a or result is null when I hit the getCurrentDoc- function althought I get the data I need from getCustomerGuidId function
var a = result;-> tried to pass it to a new var..IDK.. I
thought it will help... it didn't.
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,-> here it's null
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});
You can try something like this will help to pass value to nested ajax call
function test(){
var myText = 'Hello all !!';
$.get({
//used the jsonplaceholder url for testing
'url':'https://jsonplaceholder.typicode.com/posts/1',
'method':'GET',
success: function (data) {
//updating value of myText
myText = 'welcome';
$.post({
'url':'https://jsonplaceholder.typicode.com/posts',
'method':'POST',
//data.title is the return value from get request to the post request
'data':{'title':data.title},
'success':function (data) {
alert(data.title +'\n' + myText);//your code here ...
}
});
}
});
}
An old question and you've likely moved on, but there's still no accepted answer.
Your setTimeout takes an anonymous function, so you are losing your binding; if you have to use a Timeout for some reason, you need to add .bind(this) to your setTimeout call (see below)
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,
success: function (data) {
}
});
}.bind(this), 2000);
At a guess you're using a Timeout because you want to ensure that your promise (i.e. the first ajax call) is resolving prior to making the nested call.
If that's your intention, you can actually scrap setTimeout completely as you have the nested call in the first ajax success call, which only runs once the promise has been resolved (providing there isn't an error; if so, jQuery would call error rather than success)
Removing setTimeout means you won't lose your binding, and a should still be result (hopefully a is an object, otherwise your second call is also going to experience issues...)
Lastly, after overcoming the binding issue you wouldn't need var a = result; you should be able to pass result directly to your nested ajax call.
Good luck!
In the nested ajax you send a as a param name, not as a param value.
So you can try the following (change param to actual param name which your server expects):
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
dataType:'text',
success: function (result) {
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
data: {param: result},
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});

How to run another JS method from longPolling?

How in method with longPolling:
function getNewMessagesLong() {
pollingFishingStarts();
$request = $.ajax({
type: 'POST',
url: "listenMessageLong",
data: lastIncomingMessageLongJson,
dataType: 'json',
success: function(data) {
}, complete: getNewMessagesLong})
}
on complete to run another method?:
function pollingFishingEnds() {
document.getElementById("fishing-end").src = "resources/img/fishing-end.png";
document.getElementById("fishing-start").src = "resources/img/fishing-start-empty.png";
}
With the example you posted, you could simply do something like this, adding an anonymous function that calls your "ends" method AND restarts your polling method:
function getNewMessagesLong() {
pollingFishingStarts();
$request = $.ajax({
type: 'POST',
url: "listenMessageLong",
data: lastIncomingMessageLongJson,
dataType: 'json',
success: function(data) {
},
complete: function() {
getNewMessagesLong();
pollingFishingEnds();
}
});
}
You could also change up to a window.setInterval() long-polling paradigm that would allow you to use your complete option to set your actual end method, rather than hijacking it for long-polling.
I'm assuming here that you want to call the "end" state code after the first round completion. Otherwise, there's literally no end to your polling, unless you have some server message to terminate, in which case you need to post that code for additional information.

Ajax redirect on error

I'm calling php file through ajax call and if it returns nothing i want to redirect user to another page (It's for error reports, if it doesn't return anything it means that user logged in). Tried to add error section but it doesn't work. Any suggestions will help. Thanks! Btw, I have small jQuery function at the top of the ajax function, why it breaks my whole ajax call?
ajax.js
function loginAjax() {
//$("#email_errors").empty(); //This function doesnt work and kills whole ajax call. Here is loginAjax function call line - <button type = "submit" id = "push_button" onclick = "loginAjax(); return false">PushMe</button>
$.ajax({
url: "Classes/call_methods_login.php",
type: "POST",
dataType: "json",
data: {
login_email: $("#login_email").val(),
login_password: $("#login_password").val(),
},
success: function(data) {
$("#login_error").html(data.login_message);
}
});
}
$.ajax({
url: "Classes/call_methods_login.php",
type: "POST",
dataType: "json",
data: {
login_email: $("#login_email").val(),
login_password: $("#login_password").val(),
},
success: function(data) {
$("#login_error").html(data.login_message);
},
error: function(){
window.location.replace("http://stackoverflow.com");
}
});
}
To redirect using javascript all you need to do is override the location.href attribute.
function loginAjax() {
$.ajax({
url: "Classes/call_methods_login.php",
type: "POST",
dataType: "json",
data: {
login_email: $("#login_email").val(),
login_password: $("#login_password").val(),
},
// the success method is deprecated in favor of done.
done: function(data) {
$("#login_error").html(data.login_message);
},
fail: function(data) {
location.href="path/to/error/page";
}
});
}

Categories