I'm using pretty standard setup I think. A click on element to call a function that handles an ajax request.
My limited understanding of variable scope and callbacks when using asynchronous anything and trying to figure out jQuery deferreds is making my feeble brain hurt.
$('<div>')
.on({
click : function(){
console.log(
fetchMyData() // this will be 'undefined' but why?
)
}
})
function fetchMyData(){
$.ajax({
// ajax setup
})
.done(function(response){
console.log( response ); // shows 'hello' as expected
return response;
})
}
I get that the ajax call will not necessarily be done by the time I'm doing the console.log(), since it's asynchronous of course.
So how can I make it such that fetchMyData() will display the ajax result once it's ready?
You should change what fetchMyData function does. Try returning the promise object.
$('<div>').click(function()
{
var fetchMyDataPromise = fetchMyData() ;
fetchMyDataPromise.done(function(response)
{
console.log(response);
});
});
function fetchMyData()
{
return $.ajax({ // ajax setup });
}
You can use jQuery When like this :
$('<div>')
.on({
click : function() {
$.when(fetchMyData()).then(function(data) {
console.log(data);
});
}
});
function fetchMyData(){
return $.ajax({
// ajax setup
});
}
So how can I make it such that fetchMyData() will display the ajax result once it's ready?
You've already done that, in the .done callback. If you want fetchMyData to return the response, you have to use a synchronous call, which is usually not the right thing to do (because the UI will freeze until the response arrives).
Maybe you want to modify your function to take a callback:
function fetchMyData(thenDoThis){
$.ajax({
// ajax setup
}).done(thenDoThis)
}
function doSomethingWithResponse(response) {
// do something
}
Then call it like this:
fetchMyData(doSomethingWithResponse);
Or like this:
$('<div>').click(function() {
fetchMyData(function(response){
console.log(response);
});
});
Related
I have a code where basically I've created a function in which, by the help of jQuery ajax, I fetch a value and set it as a data attribute of an element.
then after calling the function, I store the data value in a variable.
But the problem is that I don't want to execute any code before the ajax function completes.
JS
function load_data(){
$.ajax({
.....,
success: function (response) {
$('.element').attr('data-foo', 'bar')
}
})
}
load_data(); //let the function set data first
console.log($('.element').data('foo')) //then execute this line
How to achieve this?
You can receive a callback function in load_data and execute it in the success function. Something like this:
function load_data(callback){
$.ajax({
.....,
success: function (response) {
$('.element').attr('data-foo', 'bar');
callback();
}
})
}
load_data(function() {
console.log($('.element').data('foo'));
});
Of course, if this is your real scenario, you could simply put console.log($('.element').data('foo')); directly inside the success function.
You can use, Async-Await. https://javascript.info/async-await
async function load_data(){
await $.ajax({
.....,
success: function (response) {
$('.element').attr('data-foo', 'bar')
}
});
console.log($('.element').data('foo')) //then execute this line
}
load_data(); //let the function set data first
Also, you can do it using callback as well.
function load_data(callback){
$.ajax({
.....,
success: function (response) {
$('.element').attr('data-foo', 'bar');
callback();
}
})
}
function doItLater(){
console.log($('.element').data('foo')) //then execute this line
}
load_data(doItLater); //let the function set data first
You can pass the data as a parameter to doItLater for getting data to your current scope.
try using .done()
load_data()
.done(function(dataResponse){
console.log($('.element').data('foo')) //then execute this line
}); //let the function set data first
the code inside will run after a your ajax call is responded and dataResponse has any response from you ajax call
This is not directly possible due to Asynchronous ajax call.
There are two ways to achieve what you want
1.
Create a function/s for the code you want to execute after successful ajax request
Call that function/s from ajax success block
Eg.
function load_data(){
$.ajax({
.....,
success: function (response) {
$('.element').attr('data-foo', 'bar');
console.log($('.element').data('foo')); // Your code goes here
}
})
}
2
Return $.ajax in load_data function
And use .then or .done function for load_data itself
Eg.
function load_data(){
return $.ajax({
.....,
success: function (response) {
$('.element').attr('data-foo', 'bar')
}
})
}
load_data().done(function() {
console.log($('.element').data('foo')); // Your code goes here
});
However, .done and .then do not behave the same. In particular, if a standard promise callback returns another promise, this will delay the resolution of all later promises. jQuery's then behaves like this, but done does not. It is not possible for a done callback to delay the resolution of later callbacks.
Ajax is asynchronous. So, you have to listen for success event and do your stuff. You might achieve something similar to your needs by using await/async
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/async_function
const load_data = async () => {
return await fetch('https://exmaple.com');
}
load_data();
$('.element').attr('data-foo', 'bar')
You could just put the console log inside of the success callback, after you set the element attribute.
If you don't want the console log written inside load_data (maybe you want to make load_data reusable, without the console log), you could put the console log in a callback function and pass the callback to load_data and call it in the ajax success function:
function load_data(cb){
$.ajax({
.....,
success: function (response) {
$('.element').attr('data-foo', 'bar')
cb();
}
})
}
function callback() {
console.log($('.element').data('foo'))
}
load_data(callback);
Another option is to set async: false in the ajax settings object, which would prevent following code from being executed before the ajax function resolves, but this is not generally a recommended practice.
with this:
$.when(load_data()).then(console.log($('.element').data('foo')));
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
When running get_style_guide_version() the console will return the expected data, but what prints in the browser is undefined. Why is that?
function get_style_guide_version() {
var jqxhr = $.getJSON( '/package.json', function() {
})
.done(function(data) {
output = data.version;
console.log(output);
return output;
});
}
$( document ).ready(function() {
document.write(get_style_guide_version());
});
There is two issues with the code:
The function actually returns nothing. Your return statement is inside the .done() function of your ajax request.
That request is done asynchronously and will most certainly not have been completed before your get_style_guide_version completes.
If you did the document.write part instead of the console.out, it would work as expected.
On the document ready function you are trying to write the results of get_style_guide_version(), which is running an async process
So the function completes before the async has returned so that wont work.
What you should do is have another function that is called manually that writes to the document and is called when the .done promise fires.
function get_style_guide_version() {
var jqxhr = $.getJSON( '/package.json', function() {
})
.done(function(data) {
output = data.version;
console.log(output);
write(output);
});
}
$( document ).ready(function() {
document.write(get_style_guide_version());
});
function write(val){
document.write(val);
}
or
function get_style_guide_version(done) {
var jqxhr = $.getJSON( '/package.json', function() {
})
.done(function(data) {
output = data.version;
console.log(output);
done(output);
});
}
$( document ).ready(function() {
document.write(get_style_guide_version(function(val){
document.write(val);
}));
});
Simple answer is, its an asynchronous request, function wont wait for the success event to happen..
When you write return output, you are returning in the done() callback. Not in the get_style_guide_version method.
You should use another callback to write the output in your browser.
I have this code:
function dialogTexts(message) {
var langText = $.ajax({
type: 'GET',
url: '/index.php/main/dialogtexts',
dataType: 'json'
});
langText.done(function(data) {
message(data);
});
langText.fail(function(ts) {
alert(ts.responseText);
});
}
dialogTexts(function(text) {
alert(text.delete);
});
I'm using a callback to alert the string text.delete (in above code), but I want to do something like:
dialogTexts(function(text) {
return text;
});
var deleteConfirmationDialogText = dialogTexts.delete;
alert(deleteConfirmationDialogText); //deleteConfirmationDialogText is undefined
dialogTexts is a function and it does not have a property .delete. That's why dialogTexts.delete is undefined when you try to use it. You simply can't use the kind of shortcut you're trying to do.
Also, the return statement in here:
dialogTexts(function(text) {
return text;
});
is doing nothing. It's just returning to the caller of that callback which is inside of dialogTexts() and that caller is not doing anything with the return value so return text is doing nothing.
If you want to alert the text, you will have to do what you first had:
dialogTexts(function(text) {
alert(text.delete);
});
That is the only real way to do it and this is a consequence of how asynchronous programming works with AJAX calls. There are some other techniques for handling callbacks (such as promises), but they all require you to process the asynchronously returned data in a callback function. That's just the nature of asynchronous programming.
I am writing a function that makes a http call to a web service, grabs some data and calls another function based on this data. If the service is down, the second function should not be called. I thought the obvious way to do this would be to write $.when(func1()).done(func2); but this will trigger func2 even when the request is aborted. I realise that I can do a workaround by calling func2 within the success function of func1's $.getJSON method, but I would like to use the deferred syntax if possible. Can anyone suggest how to handle this in a way that is consistent with the deferred object syntax?
function checker() {
console.log("in checker");
$.getJSON("http://djdjdjdjdjinvalidUrl.dkdkdk", function(data) {
console.log("in success function");
});
}
function crosser(data) {
console.log("in crosser");
}
$(document).ready(function(){
$.when(checker()).done(crosser);
});
See jsFiddle for a live example.
you need to return a promise from checker
function checker() {
console.log("in checker");
return $.getJSON("http://djdjdjdjdjinvalidUrl.dkdkdk", function(data) {
console.log("in success function");
});
}
Demo: Fiddle
Also there is no need to use $.when()
$(document).ready(function(){
checker().done(crosser);
});
Demo: Fiddle
For asynchronous events like $.getJSON, you need to use the actual deferred object. I've updated your jsfiddle with this object in use: http://jsfiddle.net/wM7aP/1/
Code:
function checker() {
var dfd = new jQuery.Deferred();
console.log("in checker");
$.getJSON("http://djdjdjdjdjinvalidUrl.dkdkdk", function(data) {
//handle data here
dfd.resolve( "hurray" );
});
return dfd.promise();
}
function crosser(data) {
console.log("in crosser");
}
$(document).ready(function(){
$.when(checker()).done(crosser);
});
var ajaxStuff = (function () {
var doAjaxStuff = function() {
//an ajax call
}
return {
doAjaxStuff : doAjaxStuff
}
})();
Is there any way to make use of this pattern, and fetch the response from a successful ajaxcall when calling my method? Something like this:
ajaxStuff.doAjaxStuff(successHandler(data){
//data should contain the object fetched by ajax
});
Hope you get the idea, otherwise I'll elaborate.
Two things:
1. Add a parameter to the doAjaxStuff function.
2. When invoking doAjaxStuff, pass in an anonymous function (or the name of a function)
var ajaxSuff = (function () {
var doAjaxStuff = function(callback) {
// do ajax call, then:
callback(dataFromAjaxCall);
}
return {
doAjaxStuff : doAjaxStuff
}
})();
// calling it:
ajaxStuff.doAjaxStuff(function(data){
//data should contain the object fetched by ajax
});
Just let doAjaxStuff accept a callback:
var doAjaxStuff = function(callback) {
// an ajax call
// Inside the Ajax success handler, call
callback(response); // or whatever the variable name is
}
Depending on your overall goals, you could also use deferred objects instead (or in addition). This makes your code highly modular. For example:
var doAjaxStuff = function() {
// $.ajax is just an example, any Ajax related function returns a promise
// object. You can also create your own deferred object.
return $.ajax({...});
}
// calling:
ajaxStuff.doAjaxStuff().done(function(data) {
// ...
});
I believe you need to read the jQuery docs for jQuery.ajax. You could make a call as simple as:
$.ajax('/path/to/file').success(function (data) {
doStuff();
})