Once again having problems being a new to javascript. I want to get the reply from my PHP script using JQuery's get. Here's my function
function getNext(){
var returnData = null;
$.get("get.php", {task:'next'}, function(responseText){
returnData = responseText; }, "text");
return returnData;
}
Now obviously the function returns null even though the request was successful. Why?
Thanks for your help in advance.
Because ajax is asynchronous, it acts independently on its own and so by the time the return statement completes, it hasn't been assigned yet.
function getNext(){
var returnData;
$.ajax({
url: "get.php",
data: {task:'next'},
success: function(responseText) { returnData = responseText },
async: false;
});
return returnData;
}
Note that this may "freeze" the UI because Javascript is single threaded -- it will wait until it receives the response from the server.
You may want to refactor it so that the action is called in the success callback. Could you show us what triggers the invokation of the getNext method?
try this
function getNext(){
var returnData = null;
$.get("get.php", {task:'next'},
function(responseText){
returnData = responseText;
alert('Data ' + responseText);
});
}
You will have to poll whether returnData contains actual data that you want periodically (or put your code into the callback method)
Related
I can't seem to manage to break out of my each loop if the ajax returns an error. I've tried
return false;
and other similar thing but the $.each still continues to run.
I need to be able to do this so that I can display error messages from my back end after posting it via ajax(I know this is bad practice however a client needed to be able to be able to send multiple forms off at once.).
Can anyone explain what I've done wrong?
var postAll = function(button_clicked)
{
e.preventDefault();
var form_response = [];
var formsCollection = document.getElementsByTagName("form");
$.each(formsCollection, function (key, value)
{
console.log(value.action);
console.log(value.id);
var url = value.action;
var id = value.id;
var data = ($('#' + id + '').serialize());
if (id == 'additionalInfo')
{
data = {'Add_info': $('#Add_info').val(),};
}
if (id != 'DONE')
{
$.ajax({
type: "POST",
dataType: 'json',
url: url,
beforeSend: function (xhr)
{
xhr.setRequestHeader('X-CSRF-TOKEN',$("#token").attr('content'));
},
data: data,
success: function (data)
{
console.log('success'); // show response from the php script.
form_response.push(data); // show response from the php script.
},
error: function (data)
{
console.log('fail'); // show response from the php script.
display_errors(data, id); // show response from the php script.
return true;
}
});
}
});
}
AJAX is asynchronous, when executing your $.each function it will execute the AJAX call and "Not wait" for the others to finish
To solve your problem you'll have to write a function that will execute the first ajax call and in the success it will execute itself again with the second ajax call.
Example:
var data = [form1,form2...etc];
function letsLoop(data,index = 0){
$.ajax({
url:....
success: function(){
letsLoop(data,index+1);
},
error: function(){
}
});
}
and here you call your function:
letsLoop(data,0);
If by breaking out of the loop you mean the return in your error handler, then it won't work as you think it would.
Your loop creates asynchronous requests 'at once'. Then each of these requests is handled by the browser (more or less simultaneously), then come responses. So by the time your error handler runs the loop has long finished.
BTW, the return in your case relates to the error handler, not the function inside the loop.
So, to achieve what you want you should 'queue' your AJAX requests and perform them one by one.
One possible solution is to create an array of forms then take (and remove it from the array) the first one, perform a request, on a response repeat the whole thing, and keep repeating until the array is empty.
i have small issue with exchanging data in between methods in a JavaScript object (class):
var TEST = (function () {
var TEST = function() {
};
TEST.prototype.get = function() {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: function (data) {
return data; // if i console log this i will get a json obj
}
});
};
TEST.prototype.parse = function(data) {
$.each(this.get(), function(k, v){
console.log(v);
});
};
return TEST;
})();
so i am trying to call one method in the each statement in another method. the issue is that
the response is undefined.
i also tried it like this, but with he same result
var testing = new TEST();
var get = testing.get();
testing.parse(get);
What am i missing? how can i return the data from this.get to be used in this.parse.
thanks
$.ajax() per default is asynchronous. That means, that the execution of your function get() wont wait until the request is finished. Hence you return no value from it, which results in undefined being returned.
In order to have your get() function be able to return a value, you would have to do the request in a synchronous way and set a variable in the outer function (as success itself is just another function, whose return value is not caught):
TEST.prototype.get = function() {
var result;
$.ajax({
type: "GET",
url: "http://test.com/getall",
async: false, // this is the important part!
dataType: "json",
success: function (data) {
result = data;
}
});
return result;
};
EDIT
As mentioned by #pebbl, this will halt the execution of all your scripts, until the request is done. Hence your whole page will be blocked for the time being.
The general approach is to use callbacks in such cases, which will be executed once the requests finished. So in your case something like this:
TEST.prototype.get = function( cb ) {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: function (data) {
cb( data );
}
});
};
with later on calling like this:
var testing = new TEST();
testing.get( function( data ) {
testing.parse( data );
});
You can't construct your function this way as you are relying on an asyncronous call, which will return it's result outside of the normal execution flow. The only way you can actually receive the result of your .get function is to use a callback.
Put simply your value isn't being returned from the .get function, it's being returned from the callback you are passing into jQuery's .ajax method.
You'd be far better off redesigning your code so as to still support the asyncronous call -- rather than disabling async.
A rough idea is to change your parse function like so:
TEST.prototype.parse = function(data) {
this.get(function(result){
$.each(result, function(k, v){
console.log(v);
});
});
};
And to change your get function accordingly:
TEST.prototype.get = function(callback) {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: callback
});
};
The above is just a quick example, you'd be wise reading up on the following jQuery topics:
http://api.jquery.com/promise/
http://api.jquery.com/category/deferred-object/
If you design your code around the promise pattern you'll find it complicated at first, but it gives you a lot of power in your code -- and gets around the whole callback stacking madness you can end up with when dealing in ajax calls.
Whilst it's not entirely clear from the jQuery.ajax documentation, this function returns a jqXHR object which implements the promise interface. So this means you can use the promise methods done, always and fail.
http://api.jquery.com/jQuery.ajax/
I have a javascript function called GetRequest() that calls the server with $.ajax() and receives a json string:
function GetRequest(ThePage) {
RequestedPage = parseInt(ThePageNumber,10);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "../Pages/MyPage.aspx/GetPage",
data: "{'ThePage':'" + ThePageNumber + "'}",
dataType: "json",
success: function (msg) {
var data = msg.hasOwnProperty("d") ? msg.d : msg;
OnSucessCallBack(data);
},
error: function (xhr, status, error) {
alert(xhr.statusText);
}
});
};
I have a function called ShowData() that calls GetRequest() and must wait until GetRequest receives its data before continuing.
function ShowData() {
//some code that determines the page number
GetRequest(ThePageNumber);
//wait until the data is in
};
I use GetRequest in several places so I can't use its success function in the context of ShowData.
How do I make my function ShowData pause its execution until GetRequest is finished? I thought of changing the OnSuccessCallBack function and determine which function initially called GetRequest() but I'm not sure on how to best do this.
Thanks for your suggestions.
add a function pass-in to GetRequest like so:
function GetRequest(pageNumber, successCallback){
//I admit this isn't "elegant" but it's most assuredly readable
var callback;
if (successCallback == null) {
callback = //default callback definition here
} else {
callback = successCallback;
}
//do everything else the same here
//except use the callback defined above
}
This gives you the flexibility to add in a separate callback handler for the onsuccess
Alternately, do the same as above, but use the "onComplete" handler unless you need the data specifically on the return (it doesn't appear as tho you do).
I'm going to strenuously suggest that you do use callbacks for asynchronous code instead of trying to shoehorn in sync requests. It's much better to just adopt a coding style that revolves around async requests when working in javascript, especially where you're already doing AJAX (which is by definition intended to be async).
Pass async:false along with the ajax options..
$.ajax({
type: "POST",
async:false,
.
.
.
});
You can make your call only synchronous by using ajax prefilters:
function ShowData() {
//some code that determines the page number
$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
options.async = false;
});
GetRequest(ThePageNumber);
//wait until the data is in
};
function vote_helper(content_id, thevote){
var result = "";
$.ajax({
type:"POST",
url:"/vote",
data:{'thevote':thevote, 'content_id':content_id},
beforeSend:function() {
},
success:function(html){
result = html;
}
});
return result;
};
I want to return the result. But it's returning blank string.
Short answer, you can't.
Long answer, .ajax uses a callback to return the value. This means that the value may or may not have been returned already by the time the return fires. But either way, it's being done so in another context.
If you're looking to make this simulate returning a value, add a new argument to your function that will replace the ajax callback. Something such as:
function vote_helper(content_id, thevote, callback){
var result = "";
$.ajax({
type:"POST",
url:"/vote",
data:{'thevote':thevote, 'content_id':content_id},
beforeSend:function() {
},
success:callback
});
return result;
};
vote_helper(x,y,function(html){
result = html;
});
But work-around or not, the reply will never be in the same working path as the code that calls the function. You need to await the response and pick up processing from there.
Since you're making an AJAX call, you need to process the result of the AJAX call in the success callback:
function vote_helper(content_id, thevote){
$.ajax({
type:"POST",
url:"/vote",
data:{'thevote':thevote, 'content_id':content_id},
beforeSend:function() {
},
success:function(html){
/* Do something like call a function with html */
}
});
};
The ajax won't complete by the time your function ends, so you can't return a result. Instead you have to modify your function to accept a callback, and call that callback with the result:
function vote_helper(content_id, thevote, callback) { // extra callback argument
$.ajax({
type: "POST",
url: "/vote",
data: {'thevote':thevote, 'content_id':content_id},
beforeSend: function() {},
// Point directly to the callback here
success: callback
});
};
If you want the UI to be completely unresponsive while waiting for the server's response, you could do the following:
function vote_helper(content_id, thevote){
var result = "";
$.ajax({
type:"POST",
async: false, //This line will make your code work
url:"/vote",
data:{'thevote':thevote, 'content_id':content_id},
beforeSend:function() {
},
success:function(html){
result = html;
}
});
return result;
};
But nobody wants the UI to hang, so the real answer is what other suggested, instead of returning a value, your method should take a callback that will be passed the 'return value' when your asynchronous method returns.
I have the following function which works great, i used JSONP to overcome cross-domain, wrote an http module to alter the content-type and didn't append a callback name in the url.
function AddSecurityCode(securityCode, token) {
var res=0;
$.ajax({ url: "http://localhost:4000/External.asmx/AddSecurityCode",
data: { securityCode: JSON.stringify(securityCode),
token: JSON.stringify(token)
},
dataType: "jsonp",
success: function(json) {
alert(json); //Alerts the result correctly
res = json;
},
error: function() {
alert("Hit error fn!");
}
});
return res; //this is return before the success function? not sure.
}
the res variable is alwayes comes undefined. and i can't use async=false with jsonp.
so how can i return the result to outside the function??
and i sure need to do that for subsequant calls.
Please advice, thanks.
The problem is i can't return the result value outside this function
You simply cannot do this.
You have to rewrite your code flow so that AddSecurityCode takes a callback parameter (i.e. a function to run) that you then invoke inside your success callback:
function AddSecurityCode(securityCode, token, callback) {
$.ajax({
....
success: function(json) {
alert(json); //Alerts the result correctly
callback(json); // HERE BE THE CHANGE
}
....
});
}
You have res declared inside the function, making it's scope local to that function. So there's a start. Declare res outside the function and see what happens.
Add async: false to the ajax request object
$.ajax({
...
async: false,
...
});
return res;
But this is not recommended since it will block the browser and will seen as not responding until the ajax call completed. Async process should use callback function like the other answer mentioning