Im trying to add an optional callback inside an AJAX successful execution, but I can't seem to get the callback to run when I want it to.
heres and example of my AJAX code
function someAjaxFunction(hosturl, callback){
$.ajax({
type: "GET",
url: hosturl,
data: {'something': 'code' },
dataType: 'json',
success: function(html){
var arr = $.map(html, function(val) { return val; });
if(arr[0] != 'false'){
console.log('1');
console.log('2');
if (callback) {
console.log('calling the callback')
callback();
}
console.log('3');
}else{
console.log('fail')
}
}
});
}
here is the callback and example of how the AJAX is being executed
function thisIsACallBack(){
console.log("i'm a callback");
}
someAjaxFunction("some url", thisIsACallBack);
If I run this code the console outputs.
1
2
3
i'm a callback
I can even remove the callback if-condition all together and I would still get the same output.
Also is here a better way to handle my Ajax return currently my response wrapped inside a json object. If the database can't find the object I have to place 'false' inside an array and convert it to a json object before echoing it back to ajax.
Couse you have to pass your callback as string to your function
someAjaxFunction("some url", thisIsACallBack); // <-- Wrong thisIsACallBack will be triggered after someAjaxFunction as some separate function call
like this
someAjaxFunction("some url", "thisIsACallBack()"); // <- Correct way
// Then call eval( callback ); inside Ajax success
....
success: function(html){
...
eval( callback );
}
your problem was that in case of this code someAjaxFunction("some url", thisIsACallBack); it was triggering someAjaxFunction then thisIsACallBack function as you written someAjaxFunction name not as string
UPDATE
if you have to pass params to your callback your option is
someAjaxFunction("some url", function(param1){
thisIsACallBack(param1)
); } );
...
success: function(html){
...
callback( yourArray );
}
JavaScript has many ways how you can pass callbacks depends on your need
Related
I'm not so much pro in javascript variable scopes and got stuck with one question.
If i have function which dose ajax call and then call my callback
function doAjaxFunc(param, callback)
{
$.ajax({
type: 'GET',
url: '/some/url/'+param,
success: function(data){
callback(data);
},
dataType:'json'
});
}
function someCallback1(ajaxResp){
// DO someting 1
}
function someCallback2(ajaxResp){
// DO someting 2
}
// exec
doAjaxFunc(1, someCallback1);
doAjaxFunc(2, someCallback2);
As ajax is async and it can be that sever will process param=1 case longer then param=2 is it possible that someCallback1 and someCallback2 will process not their responses. I mean callback argument value will be somehow mixed ?
If possible give some explanation details in answer
I mean callback argument value will be somehow mixed?
No. The callbacks will be called in completely separate invocations within scope of the originating AJAX success handler. There will be no cross-contamination of the data from either request.
Also, just as an aside, you can change this:
success: function(data){
callback(data);
},
To just this:
success: callback,
Check this example , i hope it is some helpful to understand scope in JavaScript
var isFirstCall=false;
function doAjax(param)
{
if(!isFirstCall)
{
//for example after do ajax
var millisecondsToWait = 1000;
setTimeout(function() {
console.log(param);
}, millisecondsToWait);
}
isFirstCall=true;
console.log(param);
}
doAjax('first call');
doAjax('second call');
I have looking for the solution with my case. In other question variable from ajax success will execute like this:
$.ajax({
...,
success: function(data) {
myFunction(data);
});
myFunction(data){
// process the data here ..
}
But in my case I call another ajax(2) with ajax(1). And really need that variable from ajax(2) to ajax(1) for process. My code look like this:
$("#formVerify").submit(function(event) {
$.ajax({
....
success: function(data){
var result= call_id(data.id);
console.log(result);
}
});
});
function call_id(data) {
var output = null;
$.ajax({
....
success: function(result){
output = result;
}
});
return output;
}
the result will always null because I set output to, or sometimes it is undefined if I don't set the value to null. I tried async: false but in my machine it wouldn't work. Need help thank you
Remember Ajax call doesn't return result, you can't use return statement in ajax call. You can get the result only using callback/promises.
Change you first ajax call to pass the callback instead of trying to get the return value:
$("#formVerify").submit(function(event) {
$.ajax({
....
success: function(data){
call_id(data.id, function(result){
console.log(result);
});
}
});
});
and change your second ajax call_id function to take callback as parameter like this:
function call_id(data, callback) {
$.ajax({
....
success: callback
});
}
Apologies if this is a duplicate question, I've followed some steps from another question which didn't seem to help me. I am trying to retrieve some JSON data, store part of the data into a variable and use that variable in a separate function outside of the AJAX request.
My expected response from the json data is http://localhost:8000/tutorials/retrieve/?page=2 (This response shows if I log the variable inside of the AJAX code) however the actual response I get when I try to log the variable from another function is as follows:
n.Event {originalEvent: MouseEvent, type: "click", timeStamp: 1436727171161, jQuery21304066238570958376: true, toElement: div#loadmore.recentTutorials…}
Here is the current code
var recentFirstPage = '';
function retrieveTutorials(){
$.ajax({
type: "GET",
url: "/tutorials/retrieve",
dataType: "json",
success: function(data){
**some unrelated parsing code here**
//Set the variable to what I need
recentFirstPage = data.next_page_url;
},
error: function() {
alert("An error occurred processing AJAX request.");
}
});
}
$('#main-content-wrap').on('click', '.recentTutorials', function(recentFirstPage){
//Does not return expected result
console.log(recentFirstPage);
});
When I click .recentTutorials I expect the console to log the data from JSON however it doesn't. Can someone help clear up my error(s)?
The reason that it doesn't log the data from JSON s that the call is asynchronous. This means that the function will execute top to bottom without waiting for the call to finish.
One method that's used is to leverage deferred objects which return a promise on completion. You can accept an anonymous function to the invoker function so that it's call back is executed within the scope of the click.
Observe:
function retrieveTutorials(){
return $.ajax({
type: "GET",
url: "/tutorials/retrieve",
dataType: "json"
});
}
$('#main-content-wrap').on('click', '.recentTutorials', function(){
//store our function call as an ajax promise
var promise = retrieveTutorials();
//wait for the ajax to return so we can mutate the data
promise.done(function(data){
//now our data will be properly
recentFirstPage = data.next_page_url;
});
});
It seems to me that you are trying to log the data before the ajax is completed. It`s better to use deferreds . Try this:
function retrieveTutorials(){
return $.ajax({ // will return deferred object
type: "GET",
url: "/tutorials/retrieve",
dataType: "json",
success: function(data){
**some unrelated parsing code here**
//Set the variable to what I need
recentFirstPage = data.next_page_url;
},
error: function() {
alert("An error occurred processing AJAX request.");
}
});
}
$.when( retrieveTutorials() ).done(function ( data ) {
console.log(recentFirstPage);
});
The parameter in your click handler is the last and final nail in your coffin. It's always the jquery event and you shouldn't handle it at all.
You do need to call the retrieveTutorials() function within the handler and you need to pass it a callback function that will be executed on success. So your retrieveTutorials() function will look something like this:
function retrieveTutorials(success){
$.ajax({ type: "GET", url: "/tutorials/retrieve",
dataType: "json",
success: success,
error: function() { alert("An error occurred processing AJAX request.");
} }); }
And your click handler:
$('#main-content-wrap').on('click', '.recentTutorials', function(){
retrieveTutorials(function(data){
console.log(data.next_page_url);
});
});
You can also use all the promise based goodness in the other anwers, but the above would be an idiom you'll see again and again.
So, I have two JavaScript functions:
function Generate() {
//Do something
$.ajax({data:{Svc: 'cpMain',
Cmd: 'Generate'
},
dataType: "text",
context: this,
success: genSuccess()
});
}
function genSuccess() {
//Do something
}
and in my c#, on Page_Init() I pick up the parameters from my AJAX callback to do something.
I want the order to be Generate(), callback, genSuccess(). But the order in which this is running is Generate(), genSuccess(), callback.
Am I missing something?
Provide the function reference of genSuccess to success, and not the return value of a call to genSuccess
success: genSuccess
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
The function I called inside jquery returns undefined. I checked the function and it returns correct data when I firebugged it.
function addToPlaylist(component_type,add_to_pl_value,pl_list_no)
{
add_to_pl_value_split = add_to_pl_value.split(":");
$.ajax({
type: "POST",
url: "ds/index.php/playlist/check_folder",
data: "component_type="+component_type+"&value="+add_to_pl_value_split[1],
success: function(msg)
{
if(msg == 'not_folder')
{
if(component_type == 'video')
{
rendered_item = render_list_item_video(add_to_pl_value_split[0],add_to_pl_value_split[1],pl_list_no)
}
else if(component_type == 'image')
{
rendered_item = render_list_item_image(add_to_pl_value_split[0],add_to_pl_value_split[1],pl_list_no)
}
}
else
{
//List files from folder
folder_name = add_to_pl_value_split[1].replace(' ','-');
var x = msg; // json
eval('var file='+x);
var rendered_item;
for ( var i in file )
{
//console.log(file[i]);
if(component_type == 'video')
{
rendered_item = render_list_item_video(folder_name+'-'+i,file[i],pl_list_no) + rendered_item;
}
if(component_type == 'image')
{
rendered_item = render_list_item_image(folder_name+'-'+i,file[i],pl_list_no) + rendered_item;
}
}
}
$("#files").html(filebrowser_list); //Reload Playlist
console.log(rendered_item);
return rendered_item;
},
error: function()
{
alert("An error occured while updating. Try again in a while");
}
})
}
$('document').ready(function()
{
addToPlaylist($('#component_type').val(),ui_item,0); //This one returns undefined
});
The function addToPlaylist doesn't return anything. It makes an asynchronous request, which eventually executes a callback function, which returns something. The original addToPlaylist function is long done and returned by the time this happens though, and the callback function returns to nobody.
I.e. the success: function(msg) { } code executes in a different context and at a later time than the surrounding addToPlaylist function.
Try this to see it in action:
function addToPlaylist() {
$.ajax({
...
success : function () {
alert('second'); // comes after 'first'
return null; // returns to nobody in particular
}
});
alert('first'); // comes before 'second'
return 'something'; // can only return here to caller
}
You're making your request via AJAX, which by definition is asynchronous. That means you're returning from the function before the AJAX request completes. In fact, your return statement is meaningless as it returns from the callback function, not your addToPlaylist function.
You have a couple of choices. The first one is better.
First, you can work with the asynchronous nature of the AJAX request and pass a callback into your addToPlaylist method (much like you're passing in the anonymous callback to the ajax function) and have the AJAX callback, call that function instead of doing the return. That way your request completes asynchronously and doesn't lock up your browser while it's going on.
function addToPlaylist(component_type, add_to_pl_value, pl_list_no, cb )
{
...yada yada yada...
$.ajax({
...
success: function(data) {
...
if (cb) {
cb.apply(this, rendered_item );
}
}
});
}
Second, you can add the option aSync: false to the ajax call. This will force the AJAX call to run synchronously (essentially it just loops until the call returns then calls your callback). If you do that, you need to capture a local variable in your addToPlaylist function inside the callback and assign the value(s) to it from the callback. At the end of the addToPlaylist function, return this variable as the result.
function addToPlaylist(component_type, add_to_pl_value, pl_list_no )
{
...yada yada yada...
var result = null;
$.ajax({
aSync: false,
...
success: function(data) {
...
result = rendered_item;
}
});
return rendered_item;
}
I agree with deceze. What you need to do is perform the necessary action(s) for rendered_item in the success function rather than relying on getting something back from addToPlayList().