How do I return the response from an asynchronous call?











up vote
4594
down vote

favorite
2156












I have a function foo which makes an Ajax request. How can I return the response from foo?



I tried returning the value from the success callback as well as assigning the response to a local variable inside the function and returning that one, but none of those ways actually return the response.



function foo() {
var result;

$.ajax({
url: '...',
success: function(response) {
result = response;
// return response; // <- I tried that one as well
}
});

return result;
}

var result = foo(); // It always ends up being `undefined`.









share|improve this question























  • 27




    @MaximShoustin I've added a JavaScript only answer (no jQuery) but like Felix said - "How do I return the response from an AJAX call" is really a nice way to say "How does concurrency work in JavaScript". Not to mention Angular's $http is very similar to jQuery's $.ajax anyway with some minor differences (like interoping with the digest cycle).
    – Benjamin Gruenbaum
    Dec 22 '13 at 21:42






  • 130




    Do not use async: false. It will freeze the browser and drive users away. Read blog.slaks.net/2015-01-04/async-method-patterns to learn how to work with asynchronous operations.
    – SLaks
    Jul 6 '15 at 17:22






  • 9




    It is possible like You did this by ading async: false as attribute of first parameter. See my answer below. @tvanfosson gave this solution on Stackoverflow.
    – arrowman
    Jan 29 '16 at 12:26






  • 7




    this mey help you codingbin.com/get-return-data-ajax-call
    – Manoj Kumar
    Mar 16 '16 at 10:09






  • 7




    @SLaks Someone please relay that to the website "rock star developers" at AirAsia.com. That's a great live case study (enhanced by the ajax calls taking a couple of seconds) of why never to use async: false.
    – Mâtt Frëëman
    Jul 6 '17 at 13:35















up vote
4594
down vote

favorite
2156












I have a function foo which makes an Ajax request. How can I return the response from foo?



I tried returning the value from the success callback as well as assigning the response to a local variable inside the function and returning that one, but none of those ways actually return the response.



function foo() {
var result;

$.ajax({
url: '...',
success: function(response) {
result = response;
// return response; // <- I tried that one as well
}
});

return result;
}

var result = foo(); // It always ends up being `undefined`.









share|improve this question























  • 27




    @MaximShoustin I've added a JavaScript only answer (no jQuery) but like Felix said - "How do I return the response from an AJAX call" is really a nice way to say "How does concurrency work in JavaScript". Not to mention Angular's $http is very similar to jQuery's $.ajax anyway with some minor differences (like interoping with the digest cycle).
    – Benjamin Gruenbaum
    Dec 22 '13 at 21:42






  • 130




    Do not use async: false. It will freeze the browser and drive users away. Read blog.slaks.net/2015-01-04/async-method-patterns to learn how to work with asynchronous operations.
    – SLaks
    Jul 6 '15 at 17:22






  • 9




    It is possible like You did this by ading async: false as attribute of first parameter. See my answer below. @tvanfosson gave this solution on Stackoverflow.
    – arrowman
    Jan 29 '16 at 12:26






  • 7




    this mey help you codingbin.com/get-return-data-ajax-call
    – Manoj Kumar
    Mar 16 '16 at 10:09






  • 7




    @SLaks Someone please relay that to the website "rock star developers" at AirAsia.com. That's a great live case study (enhanced by the ajax calls taking a couple of seconds) of why never to use async: false.
    – Mâtt Frëëman
    Jul 6 '17 at 13:35













up vote
4594
down vote

favorite
2156









up vote
4594
down vote

favorite
2156






2156





I have a function foo which makes an Ajax request. How can I return the response from foo?



I tried returning the value from the success callback as well as assigning the response to a local variable inside the function and returning that one, but none of those ways actually return the response.



function foo() {
var result;

$.ajax({
url: '...',
success: function(response) {
result = response;
// return response; // <- I tried that one as well
}
});

return result;
}

var result = foo(); // It always ends up being `undefined`.









share|improve this question















I have a function foo which makes an Ajax request. How can I return the response from foo?



I tried returning the value from the success callback as well as assigning the response to a local variable inside the function and returning that one, but none of those ways actually return the response.



function foo() {
var result;

$.ajax({
url: '...',
success: function(response) {
result = response;
// return response; // <- I tried that one as well
}
});

return result;
}

var result = foo(); // It always ends up being `undefined`.






javascript ajax asynchronous ecmascript-6 ecmascript-2017






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 15 at 5:12









Ry-

166k37336357




166k37336357










asked Jan 8 '13 at 17:06









Felix Kling

543k125846900




543k125846900












  • 27




    @MaximShoustin I've added a JavaScript only answer (no jQuery) but like Felix said - "How do I return the response from an AJAX call" is really a nice way to say "How does concurrency work in JavaScript". Not to mention Angular's $http is very similar to jQuery's $.ajax anyway with some minor differences (like interoping with the digest cycle).
    – Benjamin Gruenbaum
    Dec 22 '13 at 21:42






  • 130




    Do not use async: false. It will freeze the browser and drive users away. Read blog.slaks.net/2015-01-04/async-method-patterns to learn how to work with asynchronous operations.
    – SLaks
    Jul 6 '15 at 17:22






  • 9




    It is possible like You did this by ading async: false as attribute of first parameter. See my answer below. @tvanfosson gave this solution on Stackoverflow.
    – arrowman
    Jan 29 '16 at 12:26






  • 7




    this mey help you codingbin.com/get-return-data-ajax-call
    – Manoj Kumar
    Mar 16 '16 at 10:09






  • 7




    @SLaks Someone please relay that to the website "rock star developers" at AirAsia.com. That's a great live case study (enhanced by the ajax calls taking a couple of seconds) of why never to use async: false.
    – Mâtt Frëëman
    Jul 6 '17 at 13:35














  • 27




    @MaximShoustin I've added a JavaScript only answer (no jQuery) but like Felix said - "How do I return the response from an AJAX call" is really a nice way to say "How does concurrency work in JavaScript". Not to mention Angular's $http is very similar to jQuery's $.ajax anyway with some minor differences (like interoping with the digest cycle).
    – Benjamin Gruenbaum
    Dec 22 '13 at 21:42






  • 130




    Do not use async: false. It will freeze the browser and drive users away. Read blog.slaks.net/2015-01-04/async-method-patterns to learn how to work with asynchronous operations.
    – SLaks
    Jul 6 '15 at 17:22






  • 9




    It is possible like You did this by ading async: false as attribute of first parameter. See my answer below. @tvanfosson gave this solution on Stackoverflow.
    – arrowman
    Jan 29 '16 at 12:26






  • 7




    this mey help you codingbin.com/get-return-data-ajax-call
    – Manoj Kumar
    Mar 16 '16 at 10:09






  • 7




    @SLaks Someone please relay that to the website "rock star developers" at AirAsia.com. That's a great live case study (enhanced by the ajax calls taking a couple of seconds) of why never to use async: false.
    – Mâtt Frëëman
    Jul 6 '17 at 13:35








27




27




@MaximShoustin I've added a JavaScript only answer (no jQuery) but like Felix said - "How do I return the response from an AJAX call" is really a nice way to say "How does concurrency work in JavaScript". Not to mention Angular's $http is very similar to jQuery's $.ajax anyway with some minor differences (like interoping with the digest cycle).
– Benjamin Gruenbaum
Dec 22 '13 at 21:42




@MaximShoustin I've added a JavaScript only answer (no jQuery) but like Felix said - "How do I return the response from an AJAX call" is really a nice way to say "How does concurrency work in JavaScript". Not to mention Angular's $http is very similar to jQuery's $.ajax anyway with some minor differences (like interoping with the digest cycle).
– Benjamin Gruenbaum
Dec 22 '13 at 21:42




130




130




Do not use async: false. It will freeze the browser and drive users away. Read blog.slaks.net/2015-01-04/async-method-patterns to learn how to work with asynchronous operations.
– SLaks
Jul 6 '15 at 17:22




Do not use async: false. It will freeze the browser and drive users away. Read blog.slaks.net/2015-01-04/async-method-patterns to learn how to work with asynchronous operations.
– SLaks
Jul 6 '15 at 17:22




9




9




It is possible like You did this by ading async: false as attribute of first parameter. See my answer below. @tvanfosson gave this solution on Stackoverflow.
– arrowman
Jan 29 '16 at 12:26




It is possible like You did this by ading async: false as attribute of first parameter. See my answer below. @tvanfosson gave this solution on Stackoverflow.
– arrowman
Jan 29 '16 at 12:26




7




7




this mey help you codingbin.com/get-return-data-ajax-call
– Manoj Kumar
Mar 16 '16 at 10:09




this mey help you codingbin.com/get-return-data-ajax-call
– Manoj Kumar
Mar 16 '16 at 10:09




7




7




@SLaks Someone please relay that to the website "rock star developers" at AirAsia.com. That's a great live case study (enhanced by the ajax calls taking a couple of seconds) of why never to use async: false.
– Mâtt Frëëman
Jul 6 '17 at 13:35




@SLaks Someone please relay that to the website "rock star developers" at AirAsia.com. That's a great live case study (enhanced by the ajax calls taking a couple of seconds) of why never to use async: false.
– Mâtt Frëëman
Jul 6 '17 at 13:35












33 Answers
33






active

oldest

votes













1 2
next











up vote
4921
down vote



accepted
+150











→ For a more general explanation of async behaviour with different examples, please see Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference



→ If you already understand the problem, skip to the possible solutions below.




The problem



The A in Ajax stands for asynchronous . That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, $.ajax returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



Here is an analogy which hopefully makes the difference between synchronous and asynchronous flow clearer:



Synchronous



Imagine you make a phone call to a friend and ask him to look something up for you. Although it might take a while, you wait on the phone and stare into space, until your friend gives you the answer that you needed.



The same is happening when you make a function call containing "normal" code:



function findItem() {
var item;
while(item_not_found) {
// search
}
return item;
}

var item = findItem();

// Do something with item
doSomethingElse();


Even though findItem might take a long time to execute, any code coming after var item = findItem(); has to wait until the function returns the result.



Asynchronous



You call your friend again for the same reason. But this time you tell him that you are in a hurry and he should call you back on your mobile phone. You hang up, leave the house and do whatever you planned to do. Once your friend calls you back, you are dealing with the information he gave to you.



That's exactly what's happening when you do an Ajax request.



findItem(function(item) {
// Do something with item
});
doSomethingElse();


Instead of waiting for the response, the execution continues immediately and the statement after the Ajax call is executed. To get the response eventually, you provide a function to be called once the response was received, a callback (notice something? call back ?). Any statement coming after that call is executed before the callback is called.





Solution(s)



Embrace the asynchronous nature of JavaScript! While certain asynchronous operations provide synchronous counterparts (so does "Ajax"), it's generally discouraged to use them, especially in a browser context.



Why is it bad do you ask?



JavaScript runs in the UI thread of the browser and any long running process will lock the UI, making it unresponsive. Additionally, there is an upper limit on the execution time for JavaScript and the browser will ask the user whether to continue the execution or not.



All of this is really bad user experience. The user won't be able to tell whether everything is working fine or not. Furthermore, the effect will be worse for users with a slow connection.



In the following we will look at three different solutions that are all building on top of each other:





  • Promises with async/await (ES2017+, available in older browsers if you use a transpiler or regenerator)


  • Callbacks (popular in node)


  • Promises with then() (ES2015+, available in older browsers if you use one of the many promise libraries)


All three are available in current browsers, and node 7+.





ES2017+: Promises with async/await



The ECMAScript version released in 2017 introduced syntax-level support for asynchronous functions. With the help of async and await, you can write asynchronous in a "synchronous style". The code is still asynchronous, but it's easier to read/understand.



async/await builds on top of promises: an async function always returns a promise. await "unwraps" a promise and either result in the value the promise was resolved with or throws an error if the promise was rejected.



Important: You can only use await inside an async function. Right now, top-level await isn't yet supported, so you might have to make an async IIFE to start an async context.



You can read more about async and await on MDN.



Here is an example that builds on top of delay above:



// Using 'superagent' which will return a promise.
var superagent = require('superagent')

// This is isn't declared as `async` because it already returns a promise
function delay() {
// `delay` returns a promise
return new Promise(function(resolve, reject) {
// Only `delay` is able to resolve or reject the promise
setTimeout(function() {
resolve(42); // After 3 seconds, resolve the promise with value 42
}, 3000);
});
}


async function getAllBooks() {
try {
// GET a list of book IDs of the current user
var bookIDs = await superagent.get('/user/books');
// wait for 3 seconds (just for the sake of this example)
await delay();
// GET information about each book
return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
} catch(error) {
// If any of the awaited promises was rejected, this catch block
// would catch the rejection reason
return null;
}
}

// Start an IIFE to use `await` at the top level
(async function(){
let books = await getAllBooks();
console.log(books);
})();


Current browser and node versions support async/await. You can also support older environments by transforming your code to ES5 with the help of regenerator (or tools that use regenerator, such as Babel).





Let functions accept callbacks



A callback is simply a function passed to another function. That other function can call the function passed whenever it is ready. In the context of an asynchronous process, the callback will be called whenever the asynchronous process is done. Usually, the result is passed to the callback.



In the example of the question, you can make foo accept a callback and use it as success callback. So this



var result = foo();
// Code that depends on 'result'


becomes



foo(function(result) {
// Code that depends on 'result'
});


Here we defined the function "inline" but you can pass any function reference:



function myCallback(result) {
// Code that depends on 'result'
}

foo(myCallback);


foo itself is defined as follows:



function foo(callback) {
$.ajax({
// ...
success: callback
});
}


callback will refer to the function we pass to foo when we call it and we simply pass it on to success. I.e. once the Ajax request is successful, $.ajax will call callback and pass the response to the callback (which can be referred to with result, since this is how we defined the callback).



You can also process the response before passing it to the callback:



function foo(callback) {
$.ajax({
// ...
success: function(response) {
// For example, filter the response
callback(filtered_response);
}
});
}


It's easier to write code using callbacks than it may seem. After all, JavaScript in the browser is heavily event-driven (DOM events). Receiving the Ajax response is nothing else but an event.

Difficulties could arise when you have to work with third-party code, but most problems can be solved by just thinking through the application flow.





ES2015+: Promises with then()



The Promise API is a new feature of ECMAScript 6 (ES2015), but it has good browser support already. There are also many libraries which implement the standard Promises API and provide additional methods to ease the use and composition of asynchronous functions (e.g. bluebird).



Promises are containers for future values. When the promise receives the value (it is resolved) or when it is cancelled (rejected), it notifies all of its "listeners" who want to access this value.



The advantage over plain callbacks is that they allow you to decouple your code and they are easier to compose.



Here is a simple example of using a promise:



function delay() {
// `delay` returns a promise
return new Promise(function(resolve, reject) {
// Only `delay` is able to resolve or reject the promise
setTimeout(function() {
resolve(42); // After 3 seconds, resolve the promise with value 42
}, 3000);
});
}

delay()
.then(function(v) { // `delay` returns a promise
console.log(v); // Log the value once it is resolved
})
.catch(function(v) {
// Or do something else if it is rejected
// (it would not happen in this example, since `reject` is not called).
});


Applied to our Ajax call we could use promises like this:



function ajax(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(this.responseText);
};
xhr.onerror = reject;
xhr.open('GET', url);
xhr.send();
});
}

ajax("/echo/json")
.then(function(result) {
// Code depending on result
})
.catch(function() {
// An error occurred
});


Describing all the advantages that promise offer is beyond the scope of this answer, but if you write new code, you should seriously consider them. They provide a great abstraction and separation of your code.



More information about promises: HTML5 rocks - JavaScript Promises



Side note: jQuery's deferred objects



Deferred objects are jQuery's custom implementation of promises (before the Promise API was standardized). They behave almost like promises but expose a slightly different API.



Every Ajax method of jQuery already returns a "deferred object" (actually a promise of a deferred object) which you can just return from your function:



function ajax() {
return $.ajax(...);
}

ajax().done(function(result) {
// Code depending on result
}).fail(function() {
// An error occurred
});


Side note: Promise gotchas



Keep in mind that promises and deferred objects are just containers for a future value, they are not the value itself. For example, suppose you had the following:



function checkPassword() {
return $.ajax({
url: '/password',
data: {
username: $('#username').val(),
password: $('#password').val()
},
type: 'POST',
dataType: 'json'
});
}

if (checkPassword()) {
// Tell the user they're logged in
}


This code misunderstands the above asynchrony issues. Specifically, $.ajax() doesn't freeze the code while it checks the '/password' page on your server - it sends a request to the server and while it waits, immediately returns a jQuery Ajax Deferred object, not the response from the server. That means the if statement is going to always get this Deferred object, treat it as true, and proceed as though the user is logged in. Not good.



But the fix is easy:



checkPassword()
.done(function(r) {
if (r) {
// Tell the user they're logged in
} else {
// Tell the user their password was bad
}
})
.fail(function(x) {
// Tell the user something bad happened
});




Not recommended: Synchronous "Ajax" calls



As I mentioned, some(!) asynchronous operations have synchronous counterparts. I don't advocate their use, but for completeness' sake, here is how you would perform a synchronous call:



Without jQuery



If you directly use a XMLHTTPRequest object, pass false as third argument to .open.



jQuery



If you use jQuery, you can set the async option to false. Note that this option is deprecated since jQuery 1.8.
You can then either still use a success callback or access the responseText property of the jqXHR object:



function foo() {
var jqXHR = $.ajax({
//...
async: false
});
return jqXHR.responseText;
}


If you use any other jQuery Ajax method, such as $.get, $.getJSON, etc., you have to change it to $.ajax (since you can only pass configuration parameters to $.ajax).



Heads up! It is not possible to make a synchronous JSONP request. JSONP by its very nature is always asynchronous (one more reason to not even consider this option).






share|improve this answer



















  • 61




    @Pommy: If you want to use jQuery, you have to include it. Please refer to docs.jquery.com/Tutorials:Getting_Started_with_jQuery.
    – Felix Kling
    Jan 17 '13 at 10:47








  • 5




    In Solution 1, sub jQuery, I could not understand this line: If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax. (Yes, I realize my nick is a tad ironic in this case)
    – gibberish
    Feb 6 '13 at 21:07






  • 23




    @gibberish: Mmmh, I don't know how it can be made clearer. Do you see how foo is called and a function is passed to it (foo(function(result) {....});)? result is used inside this function and is the response of the Ajax request. To refer to this function, the first parameter of foo is called callback and assigned to success instead of an anonymous function. So, $.ajax will call callback when the request was successful. I tried to explain it a bit more.
    – Felix Kling
    Feb 6 '13 at 23:29








  • 33




    The Chat for this question is dead so I'm not sure where to propose outlined changes, but I propose: 1) Change the synchronous part to a simple discussion of why it's bad with no code example of how to do it. 2) Remove/merge the callback examples to only show the more flexible Deferred approach, which I think may also be a little easier to follow for those learning Javascript.
    – Chris Moschini
    Apr 16 '13 at 2:45






  • 10




    @Jessi: I think you misunderstood that part of the answer. You cannot use $.getJSON if you want the Ajax request to be synchronous. However, you should not event want the request to be synchronous, so that doesn't apply. You should be using callbacks or promises to handle the response, as it is explained earlier in the answer.
    – Felix Kling
    Oct 8 '15 at 17:44


















up vote
931
down vote













If you're not using jQuery in your code, this answer is for you



Your code should be something along the lines of this:



function foo() {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', "/echo/json");
httpRequest.send();
return httpRequest.responseText;
}

var result = foo(); // always ends up being 'undefined'


Felix Kling did a fine job writing an answer for people using jQuery for AJAX, I've decided to provide an alternative for people who aren't.



(Note, for those using the new fetch API, Angular or promises I've added another answer below)





What you're facing



This is a short summary of "Explanation of the problem" from the other answer, if you're not sure after reading this, read that.



The A in AJAX stands for asynchronous. That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, .send returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



This means when you're returning, the listener you've defined did not execute yet, which means the value you're returning has not been defined.



Here is a simple analogy



function getFive(){ 
var a;
setTimeout(function(){
a=5;
},10);
return a;
}


(Fiddle)



The value of a returned is undefined since the a=5 part has not executed yet. AJAX acts like this, you're returning the value before the server got the chance to tell your browser what that value is.



One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed.



function onComplete(a){ // When the code completes, do this
alert(a);
}

function getFive(whenDone){
var a;
setTimeout(function(){
a=5;
whenDone(a);
},10);
}


This is called CPS. Basically, we're passing getFive an action to perform when it completes, we're telling our code how to react when an event completes (like our AJAX call, or in this case the timeout).



Usage would be:



getFive(onComplete);


Which should alert "5" to the screen. (Fiddle).



Possible solutions



There are basically two ways how to solve this:




  1. Make the AJAX call synchronous (lets call it SJAX).

  2. Restructure your code to work properly with callbacks.


1. Synchronous AJAX - Don't do it!!



As for synchronous AJAX, don't do it! Felix's answer raises some compelling arguments about why it's a bad idea. To sum it up, it'll freeze the user's browser until the server returns the response and create a very bad user experience. Here is another short summary taken from MDN on why:




XMLHttpRequest supports both synchronous and asynchronous communications. In general, however, asynchronous requests should be preferred to synchronous requests for performance reasons.



In short, synchronous requests block the execution of code... ...this can cause serious issues...




If you have to do it, you can pass a flag: Here is how:



var request = new XMLHttpRequest();
request.open('GET', 'yourURL', false); // `false` makes the request synchronous
request.send(null);

if (request.status === 200) {// That's HTTP for 'ok'
console.log(request.responseText);
}


2. Restructure code



Let your function accept a callback. In the example code foo can be made to accept a callback. We'll be telling our code how to react when foo completes.



So:



var result = foo();
// code that depends on `result` goes here


Becomes:



foo(function(result) {
// code that depends on `result`
});


Here we passed an anonymous function, but we could just as easily pass a reference to an existing function, making it look like:



function myHandler(result) {
// code that depends on `result`
}
foo(myHandler);


For more details on how this sort of callback design is done, check Felix's answer.



Now, let's define foo itself to act accordingly



function foo(callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.onload = function(){ // when the request is loaded
callback(httpRequest.responseText);// we're calling our method
};
httpRequest.open('GET', "/echo/json");
httpRequest.send();
}


(fiddle)



We have now made our foo function accept an action to run when the AJAX completes successfully, we can extend this further by checking if the response status is not 200 and acting accordingly (create a fail handler and such). Effectively solving our issue.



If you're still having a hard time understanding this read the AJAX getting started guide at MDN.






share|improve this answer



















  • 11




    "synchronous requests block the execution of code and can leak memory and events" how can a synchronous request leak memory?
    – Matthew G
    Aug 16 '13 at 5:54






  • 6




    @MatthewG I've added a bounty on it in this question, I'll see what I can fish out. I'm removing the quote from the answer in the mean time.
    – Benjamin Gruenbaum
    Aug 16 '13 at 8:28






  • 11




    Just for the reference, XHR 2 allows us to use the onload handler, which only fires when readyState is 4. Of course, it's not supported in IE8. (iirc, may need confirmation.)
    – Florian Margaine
    Dec 22 '13 at 21:09








  • 5




    Your explanation of how to pass an anonymous function as a callback is valid but misleading. The example var bar = foo(); is asking for a variable to be defined, whereas your suggested foo(functim() {}); doesn't define bar
    – Robbie Averill
    Aug 7 '14 at 10:14










  • @BenjaminGruenbaum How do I return the content of result in a variable that I can use somewhere else in my code rather than printing it with html?
    – MorganFR
    Nov 8 '16 at 15:39


















up vote
327
down vote













XMLHttpRequest 2 (first of all read the answers from Benjamin Gruenbaum & Felix Kling)



If you don't use jQuery and want a nice short XMLHttpRequest 2 which works on the modern browsers and also on the mobile browsers I suggest to use it this way:



function ajax(a, b, c){ // URL, callback, just a placeholder
c = new XMLHttpRequest;
c.open('GET', a);
c.onload = b;
c.send()
}


As you can see:




  1. It's shorter than all other functions Listed.

  2. The callback is set directly (so no extra unnecessary closures).

  3. It uses the new onload (so you don't have to check for readystate && status)

  4. There are some other situations which I don't remember that make the XMLHttpRequest 1 annoying.


There are two ways to get the response of this Ajax call (three using the XMLHttpRequest var name):



The simplest:



this.response


Or if for some reason you bind() the callback to a class:



e.target.response


Example:



function callback(e){
console.log(this.response);
}
ajax('URL', callback);


Or (the above one is better anonymous functions are always a problem):



ajax('URL', function(e){console.log(this.response)});


Nothing easier.



Now some people will probably say that it's better to use onreadystatechange or the even the XMLHttpRequest variable name. That's wrong.



Check out XMLHttpRequest advanced features



It supported all *modern browsers. And I can confirm as I'm using this approach since XMLHttpRequest 2 exists. I never had any type of problem on all browsers I use.



onreadystatechange is only useful if you want to get the headers on state 2.



Using the XMLHttpRequest variable name is another big error as you need to execute the callback inside the onload/oreadystatechange closures else you lost it.





Now if you want something more complex using post and FormData you can easily extend this function:



function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
c = new XMLHttpRequest;
c.open(e||'get', a);
c.onload = b;
c.send(d||null)
}


Again ... it's a very short function, but it does get & post.



Examples of usage:



x(url, callback); // By default it's get so no need to set
x(url, callback, 'post', {'key': 'val'}); // No need to set post data


Or pass a full form element (document.getElementsByTagName('form')[0]):



var fd = new FormData(form);
x(url, callback, 'post', fd);


Or set some custom values:



var fd = new FormData();
fd.append('key', 'val')
x(url, callback, 'post', fd);


As you can see I didn't implement sync... it's a bad thing.



Having said that ... why don't do it the easy way?





As mentioned in the comment the use of error && synchronous does completely break the point of the answer. Which is a nice short way to use Ajax in the proper way?



Error handler



function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
c = new XMLHttpRequest;
c.open(e||'get', a);
c.onload = b;
c.onerror = error;
c.send(d||null)
}

function error(e){
console.log('--Error--', this.type);
console.log('this: ', this);
console.log('Event: ', e)
}
function displayAjax(e){
console.log(e, this);
}
x('WRONGURL', displayAjax);


In the above script, you have an error handler which is statically defined so it does not compromise the function. The error handler can be used for other functions too.



But to really get out an error the only way is to write a wrong URL in which case every browser throws an error.



Error handlers are maybe useful if you set custom headers, set the responseType to blob array buffer or whatever...



Even if you pass 'POSTAPAPAP' as the method it won't throw an error.



Even if you pass 'fdggdgilfdghfldj' as formdata it won't throw an error.



In the first case the error is inside the displayAjax() under this.statusText as Method not Allowed.



In the second case, it simply works. You have to check at the server side if you passed the right post data.



cross-domain not allowed throws error automatically.



In the error response, there are no error codes.



There is only the this.type which is set to error.



Why add an error handler if you totally have no control over errors?
Most of the errors are returned inside this in the callback function displayAjax().



So: No need for error checks if you're able to copy and paste the URL properly. ;)



PS: As the first test I wrote x('x', displayAjax)..., and it totally got a response...??? So I checked the folder where the HTML is located, and there was a file called 'x.xml'. So even if you forget the extension of your file XMLHttpRequest 2 WILL FIND IT. I LOL'd





Read a file synchronous



Don't do that.



If you want to block the browser for a while load a nice big .txt file synchronous.



function omg(a, c){ // URL
c = new XMLHttpRequest;
c.open('GET', a, true);
c.send();
return c; // Or c.response
}


Now you can do



 var res = omg('thisIsGonnaBlockThePage.txt');


There is no other way to do this in a non-asynchronous way. (Yeah, with setTimeout loop... but seriously?)



Another point is... if you work with APIs or just your own list's files or whatever you always use different functions for each request...



Only if you have a page where you load always the same XML/JSON or whatever you need only one function. In that case, modify a little the Ajax function and replace b with your special function.





The functions above are for basic use.



If you want to EXTEND the function...



Yes, you can.



I'm using a lot of APIs and one of the first functions I integrate into every HTML page is the first Ajax function in this answer, with GET only...



But you can do a lot of stuff with XMLHttpRequest 2:



I made a download manager (using ranges on both sides with resume, filereader, filesystem), various image resizers converters using canvas, populate web SQL databases with base64images and much more... But in these cases you should create a function only for that purpose... sometimes you need a blob, array buffers, you can set headers, override mimetype and there is a lot more...



But the question here is how to return an Ajax response... (I added an easy way.)






share|improve this answer



















  • 11




    While this answer is nice (And we all love XHR2 and posting file data and multipart data is totally awesome) - this shows syntactic sugar for posting XHR with JavaScript - you might want to put this in a blog post (I'd like it) or even in a library (not sure about the name x, ajax or xhr might be nicer :)). I don't see how it addresses returning the response from an AJAX call. (someone could still do var res = x("url") and not understand why it doesn't work ;)). On a side note - it would be cool if you returned c from the method so users can hook on error etc.
    – Benjamin Gruenbaum
    Aug 23 '13 at 5:56






  • 21




    2.ajax is meant to be async.. so NO var res=x('url').. That's the entire point of this question and answers :)
    – Benjamin Gruenbaum
    Aug 23 '13 at 17:28






  • 2




    why is there a 'c' parameter in the functions, if on the first line you're overwriting whatever value it had? am i missing something?
    – Brian H.
    Dec 21 '16 at 10:00






  • 1




    You can use parameters as a placeholder to avoid writing multiple times "var"
    – cocco
    Dec 21 '16 at 11:05






  • 5




    @cocco So you wrote misleading, unreadable code in a SO answer in order to save a few keystrokes? Please don't do that.
    – stone
    Oct 8 '17 at 6:20


















up vote
264
down vote













If you're using promises, this answer is for you.



This means AngularJS, jQuery (with deferred), native XHR's replacement (fetch), EmberJS, BackboneJS's save or any node library that returns promises.



Your code should be something along the lines of this:



function foo() {
var data;
// or $.get(...).then, or request(...).then, or query(...).then
fetch("/echo/json").then(function(response){
data = response.json();
});
return data;
}

var result = foo(); // result is always undefined no matter what.


Felix Kling did a fine job writing an answer for people using jQuery with callbacks for AJAX. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.





The core issue



The JavaScript concurrency model in the browser and on the server with NodeJS/io.js is asynchronous and reactive.



Whenever you call a method that returns a promise, the then handlers are always executed asynchronously - that is, after the code below them that is not in a .then handler.



This means when you're returning data the then handler you've defined did not execute yet. This in turn means that the value you're returning has not been set to the correct value in time.



Here is a simple analogy for the issue:




    function getFive(){
var data;
setTimeout(function(){ // set a timer for one second in the future
data = 5; // after a second, do this
}, 1000);
return data;
}
document.body.innerHTML = getFive(); // `undefined` here and not 5





The value of data is undefined since the data = 5 part has not executed yet. It will likely execute in a second but by that time it is irrelevant to the returned value.



Since the operation did not happen yet (AJAX, server call, IO, timer) you're returning the value before the request got the chance to tell your code what that value is.



One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed. Promises actively enable this by being temporal (time-sensitive) in nature.



Quick recap on promises



A Promise is a value over time. Promises have state, they start as pending with no value and can settle to:





  • fulfilled meaning that the computation completed successfully.


  • rejected meaning that the computation failed.


A promise can only change states once after which it will always stay at the same state forever. You can attach then handlers to promises to extract their value and handle errors. then handlers allow chaining of calls. Promises are created by using APIs that return them. For example, the more modern AJAX replacement fetch or jQuery's $.get return promises.



When we call .then on a promise and return something from it - we get a promise for the processed value. If we return another promise we'll get amazing things, but let's hold our horses.



With promises



Let's see how we can solve the above issue with promises. First, let's demonstrate our understanding of promise states from above by using the Promise constructor for creating a delay function:



function delay(ms){ // takes amount of milliseconds
// returns a new promise
return new Promise(function(resolve, reject){
setTimeout(function(){ // when the time is up
resolve(); // change the promise to the fulfilled state
}, ms);
});
}


Now, after we converted setTimeout to use promises, we can use then to make it count:






function delay(ms){ // takes amount of milliseconds
// returns a new promise
return new Promise(function(resolve, reject){
setTimeout(function(){ // when the time is up
resolve(); // change the promise to the fulfilled state
}, ms);
});
}

function getFive(){
// we're RETURNING the promise, remember, a promise is a wrapper over our value
return delay(100).then(function(){ // when the promise is ready
return 5; // return the value 5, promises are all about return values
})
}
// we _have_ to wrap it like this in the call site, we can't access the plain value
getFive().then(function(five){
document.body.innerHTML = five;
});





Basically, instead of returning a value which we can't do because of the concurrency model - we're returning a wrapper for a value that we can unwrap with then. It's like a box you can open with then.



Applying this



This stands the same for your original API call, you can:



function foo() {
// RETURN the promise
return fetch("/echo/json").then(function(response){
return response.json(); // process it inside the `then`
});
}

foo().then(function(response){
// access the value inside the `then`
})


So this works just as well. We've learned we can't return values from already asynchronous calls but we can use promises and chain them to perform processing. We now know how to return the response from an asynchronous call.



ES2015 (ES6)



ES6 introduces generators which are functions that can return in the middle and then resume the point they were at. This is typically useful for sequences, for example:



function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
yield 1;
yield 2;
while(true) yield 3;
}


Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility there is one particular interesting case.



If the sequence we're producing is a sequence of actions rather than numbers - we can pause the function whenever an action is yielded and wait for it before we resume the function. So instead of a sequence of numbers, we need a sequence of future values - that is: promises.



This somewhat tricky but very powerful trick lets us write asynchronous code in a synchronous manner. There are several "runners" that do this for you, writing one is a short few lines of code but is beyond the scope of this answer. I'll be using Bluebird's Promise.coroutine here, but there are other wrappers like co or Q.async.



var foo = coroutine(function*(){
var data = yield fetch("/echo/json"); // notice the yield
// code here only executes _after_ the request is done
return data.json(); // data is defined
});


This method returns a promise itself, which we can consume from other coroutines. For example:



var main = coroutine(function*(){
var bar = yield foo(); // wait our earlier coroutine, it returns a promise
// server call done here, code below executes when done
var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
console.log(baz); // runs after both requests done
});
main();


ES2016 (ES7)



In ES7, this is further standardized, there are several proposals right now but in all of them you can await promise. This is just "sugar" (nicer syntax) for the ES6 proposal above by adding the async and await keywords. Making the above example:



async function foo(){
var data = await fetch("/echo/json"); // notice the await
// code here only executes _after_ the request is done
return data.json(); // data is defined
}


It still returns a promise just the same :)






share|improve this answer



















  • 17




    ES 2016 looks like the final solution to this problem once and for all.
    – ShrekOverflow
    May 12 '15 at 16:42






  • 10




    The absolutely final solution, for once and for all? What about the totally absolutely final solution, for once and for all plus one?
    – Shmiddty
    May 13 '15 at 6:11






  • 3




    @recurf first of all "where the hell" is hardly appropriate for this site (kids are using it too, for one). Second of all - it's a function parameter, I could have named it anywhere else and it would work just as fine.
    – Benjamin Gruenbaum
    Jan 20 '17 at 0:08










  • @TDR by awaiting with async/await or with a then
    – Benjamin Gruenbaum
    Jul 17 at 18:45


















up vote
206
down vote













You are using Ajax incorrectly. The idea is not to have it return anything, but instead hand off the data to something called a callback function, which handles the data.



That is:



function handleData( responseData ) {

// Do what you want with the data
console.log(responseData);
}

$.ajax({
url: "hi.php",
...
success: function ( data, status, XHR ) {
handleData(data);
}
});


Returning anything in the submit handler will not do anything. You must instead either hand off the data, or do what you want with it directly inside the success function.






share|improve this answer



















  • 9




    This answer is completely semantic... your success method is just a callback within a callback. You could just have success: handleData and it would work.
    – Jacques
    Jan 4 '16 at 15:49






  • 3




    And what if you want to return the "responseData" outside of "handleData" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "handleData" ...
    – pesho hristov
    Feb 19 '16 at 16:02










  • @Jacques & @pesho hristov You missed this point. Submit handler is not the success method, it's the surrounding scope of $.ajax.
    – travnik
    May 28 at 12:37










  • @travnik I didn't miss that. If you took the contents of handleData and put it in the success method it would act exactly the same...
    – Jacques
    Jun 13 at 1:21


















up vote
197
down vote













The simplest solution is create a JavaScript function and call it for the Ajax success callback.



function callServerAsync(){
$.ajax({
url: '...',
success: function(response) {

successCallback(response);
}
});
}

function successCallback(responseObj){
// Do something like read the response and show data
alert(JSON.stringify(responseObj)); // Only applicable to JSON response
}

function foo(callback) {

$.ajax({
url: '...',
success: function(response) {
return callback(null, response);
}
});
}

var result = foo(function(err, result){
if (!err)
console.log(result);
});





share|improve this answer



















  • 2




    I don't know who voted it negative. But this is a work around which has worked in fact i used this approach to create a whole application. The jquery.ajax don't return data so its better to use the above approach. If it's wrong then please explain and suggest better way to do it.
    – Hemant Bavle
    Mar 28 '14 at 18:12








  • 11




    Sorry, I forgot to leave a comment (I usually do!). I downvoted it. Downvotes don't indicate factual correctness or lack of, they indicate usefulness in the context or lack of. I don't find your answer useful given Felix's which already explains this only in much more detail. On a side note, why would you stringify the response if it's JSON?
    – Benjamin Gruenbaum
    Apr 10 '14 at 9:18






  • 5




    ok.. @Benjamin i used stringify, to convert a JSON Object to string. And thanks for clarifying your point. Will keep in mind to post more elaborate answers.
    – Hemant Bavle
    Apr 10 '14 at 10:27












  • And what if you want to return the "responseObj" outside of "successCallback" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "successCallback" ...
    – pesho hristov
    Feb 19 '16 at 16:02


















up vote
165
down vote













I will answer with a horrible-looking, hand-drawn comic. The second image is the reason why result is undefined in your code example.



enter image description here






share|improve this answer



















  • 22




    A picture is worth a thousand words, Person A - Ask's person B details to fix his car, in turn Person B - Makes Ajax Call and waits for response from server for car fixing details, when response is received, Ajax Success function calls the Person B function and passes the response as argument to it, Person A receives the answer.
    – stom
    Oct 31 '16 at 17:48








  • 4




    Would be great if you added lines of code with each image to illustrate the concepts.
    – Hassan Baig
    Feb 5 at 0:32






  • 5




    The best explanation I've ever come across
    – anonymous
    Mar 31 at 15:52






  • 1




    Best Explanation
    – Vijay S
    Aug 23 at 9:42


















up vote
123
down vote













Angular1



For people who are using AngularJS, can handle this situation using Promises.



Here it says,




Promises can be used to unnest asynchronous functions and allows one to chain multiple functions together.




You can find a nice explanation here also.



Example found in docs mentioned below.



  promiseB = promiseA.then(
function onSuccess(result) {
return result + 1;
}
,function onError(err) {
//Handle error
}
);

// promiseB will be resolved immediately after promiseA is resolved
// and its value will be the result of promiseA incremented by 1.


Angular2 and Later



In Angular2 with look at the following example, but its recommended to use Observables with Angular2.



 search(term: string) {
return this.http
.get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
.map((response) => response.json())
.toPromise();


}



You can consume that in this way,



search() {
this.searchService.search(this.searchField.value)
.then((result) => {
this.result = result.artists.items;
})
.catch((error) => console.error(error));
}


See the original post here. But Typescript does not support native es6 Promises, if you want to use it, you might need plugin for that.



Additionally here is the promises spec define here.






share|improve this answer



















  • 13




    This does not explain how promises would solve this issue at all though.
    – Benjamin Gruenbaum
    Nov 4 '14 at 2:29






  • 4




    It doesn't work. promiseB will get 'undefined'
    – An Overflowed Stack
    Nov 21 '14 at 15:35






  • 3




    jQuery and fetch methods both return promises as well. I would suggest revising your answer. Though jQuery's isn't quite the same (then is there, but catch isn't).
    – Tracker1
    Feb 19 '15 at 19:24


















up vote
101
down vote













Most of the answers here give useful suggestions for when you have a single async operation, but sometimes, this comes up when you need to do an asynchronous operation for each entry in an array or other list-like structure. The temptation is to do this:



// WRONG
var results = ;
theArray.forEach(function(entry) {
doSomethingAsync(entry, function(result) {
results.push(result);
});
});
console.log(results); // E.g., using them, returning them, etc.


Example:






// WRONG
var theArray = [1, 2, 3];
var results = ;
theArray.forEach(function(entry) {
doSomethingAsync(entry, function(result) {
results.push(result);
});
});
console.log("Results:", results); // E.g., using them, returning them, etc.

function doSomethingAsync(value, callback) {
console.log("Starting async operation for " + value);
setTimeout(function() {
console.log("Completing async operation for " + value);
callback(value * 2);
}, Math.floor(Math.random() * 200));
}

.as-console-wrapper {
max-height: 100% !important;
}





The reason that doesn't work is that the callbacks from doSomethingAsync haven't run yet by the time you're trying to use the results.



So, if you have an array (or list of some kind) and want to do async operations for each entry, you have two options: Do the operations in parallel (overlapping), or in series (one after another in sequence).



Parallel



You can start all of them and keep track of how many callbacks you're expecting, and then use the results when you've gotten that many callbacks:



var results = ;
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
doSomethingAsync(entry, function(result) {
results[index] = result;
if (--expecting === 0) {
// Done!
console.log("Results:", results); // E.g., using the results
}
});
});


Example:






var theArray = [1, 2, 3];
var results = ;
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
doSomethingAsync(entry, function(result) {
results[index] = result;
if (--expecting === 0) {
// Done!
console.log("Results:", results); // E.g., using the results
}
});
});

function doSomethingAsync(value, callback) {
console.log("Starting async operation for " + value);
setTimeout(function() {
console.log("Completing async operation for " + value);
callback(value * 2);
}, Math.floor(Math.random() * 200));
}

.as-console-wrapper {
max-height: 100% !important;
}





(We could do away with expecting and just use results.length === theArray.length, but that leaves us open to the possibility that theArray is changed while the calls are outstanding...)



Notice how we use the index from forEach to save the result in results in the same position as the entry it relates to, even if the results arrive out of order (since async calls don't necessarily complete in the order in which they were started).



But what if you need to return those results from a function? As the other answers have pointed out, you can't; you have to have your function accept and call a callback (or return a Promise). Here's a callback version:



function doSomethingWith(theArray, callback) {
var results = ;
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
doSomethingAsync(entry, function(result) {
results[index] = result;
if (--expecting === 0) {
// Done!
callback(results);
}
});
});
}
doSomethingWith(theArray, function(results) {
console.log("Results:", results);
});


Example:






function doSomethingWith(theArray, callback) {
var results = ;
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
doSomethingAsync(entry, function(result) {
results[index] = result;
if (--expecting === 0) {
// Done!
callback(results);
}
});
});
}
doSomethingWith([1, 2, 3], function(results) {
console.log("Results:", results);
});

function doSomethingAsync(value, callback) {
console.log("Starting async operation for " + value);
setTimeout(function() {
console.log("Completing async operation for " + value);
callback(value * 2);
}, Math.floor(Math.random() * 200));
}

.as-console-wrapper {
max-height: 100% !important;
}





Or here's a version returning a Promise instead:



function doSomethingWith(theArray) {
return new Promise(function(resolve) {
var results = ;
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
doSomethingAsync(entry, function(result) {
results[index] = result;
if (--expecting === 0) {
// Done!
resolve(results);
}
});
});
});
}
doSomethingWith(theArray).then(function(results) {
console.log("Results:", results);
});


Of course, if doSomethingAsync passed us errors, we'd use reject to reject the promise when we got an error.)



Example:






function doSomethingWith(theArray) {
return new Promise(function(resolve) {
var results = ;
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
doSomethingAsync(entry, function(result) {
results[index] = result;
if (--expecting === 0) {
// Done!
resolve(results);
}
});
});
});
}
doSomethingWith([1, 2, 3]).then(function(results) {
console.log("Results:", results);
});

function doSomethingAsync(value, callback) {
console.log("Starting async operation for " + value);
setTimeout(function() {
console.log("Completing async operation for " + value);
callback(value * 2);
}, Math.floor(Math.random() * 200));
}

.as-console-wrapper {
max-height: 100% !important;
}





(Or alternately, you could make a wrapper for doSomethingAsync that returns a promise, and then do the below...)



If doSomethingAsync gives you a Promise, you can use Promise.all:



function doSomethingWith(theArray) {
return Promise.all(theArray.map(function(entry) {
return doSomethingAsync(entry, function(result) {
results.push(result);
});
}));
}
doSomethingWith(theArray).then(function(results) {
console.log("Results:", results);
});


Example:






function doSomethingWith(theArray) {
return Promise.all(theArray.map(function(entry) {
return doSomethingAsync(entry, function(result) {
results.push(result);
});
}));
}
doSomethingWith([1, 2, 3]).then(function(results) {
console.log("Results:", results);
});

function doSomethingAsync(value) {
console.log("Starting async operation for " + value);
return new Promise(function(resolve) {
setTimeout(function() {
console.log("Completing async operation for " + value);
resolve(value * 2);
}, Math.floor(Math.random() * 200));
});
}

.as-console-wrapper {
max-height: 100% !important;
}





Note that Promise.all resolves its promise with an array of the results of all of the promises you give it when they are all resolved, or rejects its promise when the first of the promises you give it rejects.



Series



Suppose you don't want the operations to be in parallel? If you want to run them one after another, you need to wait for each operation to complete before you start the next. Here's an example of a function that does that and calls a callback with the result:



function doSomethingWith(theArray, callback) {
var results = ;
doOne(0);
function doOne(index) {
if (index < theArray.length) {
doSomethingAsync(theArray[index], function(result) {
results.push(result);
doOne(index + 1);
});
} else {
// Done!
callback(results);
}
}
}
doSomethingWith(theArray, function(results) {
console.log("Results:", results);
});


(Since we're doing the work in series, we can just use results.push(result) since we know we won't get results out of order. In the above we could have used results[index] = result;, but in some of the following examples we don't have an index to use.)



Example:






function doSomethingWith(theArray, callback) {
var results = ;
doOne(0);
function doOne(index) {
if (index < theArray.length) {
doSomethingAsync(theArray[index], function(result) {
results.push(result);
doOne(index + 1);
});
} else {
// Done!
callback(results);
}
}
}
doSomethingWith([1, 2, 3], function(results) {
console.log("Results:", results);
});

function doSomethingAsync(value, callback) {
console.log("Starting async operation for " + value);
setTimeout(function() {
console.log("Completing async operation for " + value);
callback(value * 2);
}, Math.floor(Math.random() * 200));
}

.as-console-wrapper {
max-height: 100% !important;
}





(Or, again, build a wrapper for doSomethingAsync that gives you a promise and do the below...)



If doSomethingAsync gives you a Promise, if you can use ES2017+ syntax (perhaps with a transpiler like Babel), you can use an async function with for-of and await:



async function doSomethingWith(theArray) {
const results = ;
for (const entry of theArray) {
results.push(await doSomethingAsync(entry));
}
return results;
}
doSomethingWith(theArray).then(results => {
console.log("Results:", results);
});


Example:






async function doSomethingWith(theArray) {
const results = ;
for (const entry of theArray) {
results.push(await doSomethingAsync(entry));
}
return results;
}
doSomethingWith([1, 2, 3]).then(function(results) {
console.log("Results:", results);
});

function doSomethingAsync(value) {
console.log("Starting async operation for " + value);
return new Promise(function(resolve) {
setTimeout(function() {
console.log("Completing async operation for " + value);
resolve(value * 2);
}, Math.floor(Math.random() * 200));
});
}

.as-console-wrapper {
max-height: 100% !important;
}





If you can't use ES2017+ syntax (yet), you can use a variation on the "Promise reduce" pattern (this is more complex than the usual Promise reduce because we're not passing the result from one into the next, but instead gathering up their results in an array):



function doSomethingWith(theArray) {
return theArray.reduce(function(p, entry) {
return p.then(function(results) {
return doSomethingAsync(entry).then(function(result) {
results.push(result);
return results;
});
});
}, Promise.resolve());
}
doSomethingWith(theArray).then(function(results) {
console.log("Results:", results);
});


Example:






function doSomethingWith(theArray) {
return theArray.reduce(function(p, entry) {
return p.then(function(results) {
return doSomethingAsync(entry).then(function(result) {
results.push(result);
return results;
});
});
}, Promise.resolve());
}
doSomethingWith([1, 2, 3]).then(function(results) {
console.log("Results:", results);
});

function doSomethingAsync(value) {
console.log("Starting async operation for " + value);
return new Promise(function(resolve) {
setTimeout(function() {
console.log("Completing async operation for " + value);
resolve(value * 2);
}, Math.floor(Math.random() * 200));
});
}

.as-console-wrapper {
max-height: 100% !important;
}





...which is less cumbersome with ES2015+ arrow functions:



function doSomethingWith(theArray) {
return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
results.push(result);
return results;
})), Promise.resolve());
}
doSomethingWith(theArray).then(results => {
console.log("Results:", results);
});


Example:






function doSomethingWith(theArray) {
return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
results.push(result);
return results;
})), Promise.resolve());
}
doSomethingWith([1, 2, 3]).then(function(results) {
console.log("Results:", results);
});

function doSomethingAsync(value) {
console.log("Starting async operation for " + value);
return new Promise(function(resolve) {
setTimeout(function() {
console.log("Completing async operation for " + value);
resolve(value * 2);
}, Math.floor(Math.random() * 200));
});
}

.as-console-wrapper {
max-height: 100% !important;
}








share|improve this answer



















  • 1




    Could you explain how the if (--expecting === 0) part of the code works please? The callback version of your solution is working great for me, I just don't understand how, with that statement, you are checking the number of responses completed. Appreciate it's just lack of knowledge on my part. Is there an alternative way that check could be written?
    – Sarah
    May 28 '17 at 10:21












  • @Sarah: expecting starts out with the value of array.length, which is how many requests we're going to make. We know the callback won't be called until all of those requests are started. In the callback, if (--expecting === 0) does this: 1. Decrements expecting (we've received a response, so we're expecting one fewer response) and if the value after the decrement is 0 (we're not expecting any more responses), we're done!
    – T.J. Crowder
    May 28 '17 at 18:31


















up vote
82
down vote













Have a look at this example:



var app = angular.module('plunker', );

app.controller('MainCtrl', function($scope,$http) {

var getJoke = function(){
return $http.get('http://api.icndb.com/jokes/random').then(function(res){
return res.data.value;
});
}

getJoke().then(function(res) {
console.log(res.joke);
});
});


As you can see getJoke is returning a resolved promise (it is resolved when returning res.data.value). So you wait until the $http.get request is completed and then console.log(res.joke) is executed (as a normal asynchronous flow).



This is the plnkr:



http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/



ES6 way (async - await)



(function(){
async function getJoke(){
let response = await fetch('http://api.icndb.com/jokes/random');
let data = await response.json();
return data.value;
}

getJoke().then((joke) => {
console.log(joke);
});
})();





share|improve this answer






























    up vote
    73
    down vote













    Another approach to return a value from an asynchronous function, is to pass in an object that will store the result from the asynchronous function.



    Here is an example of the same:



    var async = require("async");

    // This wires up result back to the caller
    var result = {};
    var asyncTasks = ;
    asyncTasks.push(function(_callback){
    // some asynchronous operation
    $.ajax({
    url: '...',
    success: function(response) {
    result.response = response;
    _callback();
    }
    });
    });

    async.parallel(asyncTasks, function(){
    // result is available after performing asynchronous operation
    console.log(result)
    console.log('Done');
    });


    I am using the result object to store the value during the asynchronous operation. This allows the result be available even after the asynchronous job.



    I use this approach a lot. I would be interested to know how well this approach works where wiring the result back through consecutive modules is involved.






    share|improve this answer



















    • 9




      There is nothing special about using an object here. It would work as well if you assigned he response directly to result. It works because you are reading the variable after the async function is complete.
      – Felix Kling
      Sep 2 '15 at 13:18


















    up vote
    68
    down vote













    This is one of the places which two ways data binding that's used in many new JavaScript frameworks will work greatly for you...



    So if you are using Angular, React or any other frameworks which do two ways data binding, this issue is simply fixed for you, so in easy word, your result is undefined at the first stage, so you have got result = undefined before you receive the data, then as soon as you get the result, it will updated and get assigned to the new value which is respond of your Ajax call...



    But how you can do it in pure javascript or jQuery for example as you asked in this question?



    You can use a callback, promise and recently observable to handle it for you, for example in promises we have some function like success() or then() which will be executed when your data is ready for you, same with callback or subscribe function on observable.



    For example in your case which you are using jQuery, you can do something like this:



    $(document).ready(function(){
    function foo() {
    $.ajax({url: "api/data", success: function(data){
    fooDone(data); //after we have data, we pass it to fooDone
    }});
    };

    function fooDone(data) {
    console.log(data); //fooDone has the data and console.log it
    };

    foo(); //call happens here
    });


    For more information study about promises and observables which are newer ways to do this async stuffs.






    share|improve this answer























    • This is fine at global scope, but in some module context you probably want to ensure right context for the callback e.g. $.ajax({url: "api/data", success: fooDone.bind(this)});
      – steve.sims
      Jul 24 '17 at 6:14








    • 5




      This is actually incorrect as React is one-way data binding
      – Matthew Brent
      May 4 at 15:57










    • @MatthewBrent you are not wrong, but not right also, React props are object and if changed, they change throughout the application, but its not a way that React developer recommend to use it...
      – Alireza
      May 14 at 7:34


















    up vote
    64
    down vote













    While promises and callbacks work fine in many situations, it is a pain in the rear to express something like:



    if (!name) {
    name = async1();
    }
    async2(name);


    You'd end up going through async1; check if name is undefined or not and call the callback accordingly.



    async1(name, callback) {
    if (name)
    callback(name)
    else {
    doSomething(callback)
    }
    }

    async1(name, async2)


    While it is okay in small examples it gets annoying when you have a lot of similar cases and error handling involved.



    Fibers helps in solving the issue.



    var Fiber = require('fibers')

    function async1(container) {
    var current = Fiber.current
    var result
    doSomething(function(name) {
    result = name
    fiber.run()
    })
    Fiber.yield()
    return result
    }

    Fiber(function() {
    var name
    if (!name) {
    name = async1()
    }
    async2(name)
    // Make any number of async calls from here
    }


    You can checkout the project here.






    share|improve this answer























    • @recurf - It's not my project. You could try using their issue tracker.
      – rohithpr
      Jan 20 '17 at 15:22










    • is this similar to generator functions? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…*
      – Emanegux
      Jun 7 '17 at 3:19










    • Is this still relevant?
      – Aluan Haddad
      Mar 18 at 19:43










    • You can make use of async-await if you're using some of the newest versions of node. If someone is stuck with older versions they can use this method.
      – rohithpr
      Mar 20 at 8:18




















    up vote
    61
    down vote













    Short answer is, you have to implement a callback like this:



    function callback(response) {
    // Here you can do what ever you want with the response object.
    console.log(response);
    }

    $.ajax({
    url: "...",
    success: callback
    });





    share|improve this answer






























      up vote
      58
      down vote













      The following example I have written shows how to




      • Handle asynchronous HTTP calls;

      • Wait for response from each API call;

      • Use Promise pattern;

      • Use Promise.all pattern to join multiple HTTP calls;


      This working example is self-contained. It will define a simple request object that uses the window XMLHttpRequest object to make calls. It will define a simple function to wait for a bunch of promises to be completed.



      Context. The example is querying the Spotify Web API endpoint in order to search for playlist objects for a given set of query strings:



      [
      "search?type=playlist&q=%22doom%20metal%22",
      "search?type=playlist&q=Adele"
      ]


      For each item, a new Promise will fire a block - ExecutionBlock, parse the result, schedule a new set of promises based on the result array, that is a list of Spotify user objects and execute the new HTTP call within the ExecutionProfileBlock asynchronously.



      You can then see a nested Promise structure, that lets you spawn multiple and completely asynchronous nested HTTP calls, and join the results from each subset of calls through Promise.all.



      NOTE
      Recent Spotify search APIs will require an access token to be specified in the request headers:



      -H "Authorization: Bearer {your access token}" 


      So, you to run the following example you need to put your access token in the request headers:






      var spotifyAccessToken = "YourSpotifyAccessToken";
      var console = {
      log: function(s) {
      document.getElementById("console").innerHTML += s + "<br/>"
      }
      }

      // Simple XMLHttpRequest
      // based on https://davidwalsh.name/xmlhttprequest
      SimpleRequest = {
      call: function(what, response) {
      var request;
      if (window.XMLHttpRequest) { // Mozilla, Safari, ...
      request = new XMLHttpRequest();
      } else if (window.ActiveXObject) { // Internet Explorer
      try {
      request = new ActiveXObject('Msxml2.XMLHTTP');
      }
      catch (e) {
      try {
      request = new ActiveXObject('Microsoft.XMLHTTP');
      } catch (e) {}
      }
      }

      // State changes
      request.onreadystatechange = function() {
      if (request.readyState === 4) { // Done
      if (request.status === 200) { // Complete
      response(request.responseText)
      }
      else
      response();
      }
      }
      request.open('GET', what, true);
      request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
      request.send(null);
      }
      }

      //PromiseAll
      var promiseAll = function(items, block, done, fail) {
      var self = this;
      var promises = ,
      index = 0;
      items.forEach(function(item) {
      promises.push(function(item, i) {
      return new Promise(function(resolve, reject) {
      if (block) {
      block.apply(this, [item, index, resolve, reject]);
      }
      });
      }(item, ++index))
      });
      Promise.all(promises).then(function AcceptHandler(results) {
      if (done) done(results);
      }, function ErrorHandler(error) {
      if (fail) fail(error);
      });
      }; //promiseAll

      // LP: deferred execution block
      var ExecutionBlock = function(item, index, resolve, reject) {
      var url = "https://api.spotify.com/v1/"
      url += item;
      console.log( url )
      SimpleRequest.call(url, function(result) {
      if (result) {

      var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
      return item.owner.href;
      })
      resolve(profileUrls);
      }
      else {
      reject(new Error("call error"));
      }
      })
      }

      arr = [
      "search?type=playlist&q=%22doom%20metal%22",
      "search?type=playlist&q=Adele"
      ]

      promiseAll(arr, function(item, index, resolve, reject) {
      console.log("Making request [" + index + "]")
      ExecutionBlock(item, index, resolve, reject);
      }, function(results) { // Aggregated results

      console.log("All profiles received " + results.length);
      //console.log(JSON.stringify(results[0], null, 2));

      ///// promiseall again

      var ExecutionProfileBlock = function(item, index, resolve, reject) {
      SimpleRequest.call(item, function(result) {
      if (result) {
      var obj = JSON.parse(result);
      resolve({
      name: obj.display_name,
      followers: obj.followers.total,
      url: obj.href
      });
      } //result
      })
      } //ExecutionProfileBlock

      promiseAll(results[0], function(item, index, resolve, reject) {
      //console.log("Making request [" + index + "] " + item)
      ExecutionProfileBlock(item, index, resolve, reject);
      }, function(results) { // aggregated results
      console.log("All response received " + results.length);
      console.log(JSON.stringify(results, null, 2));
      }

      , function(error) { // Error
      console.log(error);
      })

      /////

      },
      function(error) { // Error
      console.log(error);
      });

      <div id="console" />





      I have extensively discussed this solution here.






      share|improve this answer






























        up vote
        55
        down vote













        2017 answer: you can now do exactly what you want in every current browser and node



        This is quite simple:




        • Return a Promise

        • Use the 'await', which will tell JavaScript to await the promise to be resolved into a value (like the HTTP response)

        • Add the 'async' keyword to the parent function


        Here's a working version of your code:



        (async function(){

        var response = await superagent.get('...')
        console.log(response)

        })()


        await is supported in all current browsers and node 8






        share|improve this answer



















        • 6




          Unfortunately, this works only with functions that return promises – for example it doesn't work with Node.js API, which uses callbacks. And I wouldn't recommend using it without Babel, because not everyone uses "current browsers".
          – Michał Perłakowski
          Jun 8 '17 at 6:47






        • 1




          @MichałPerłakowski node 8 includes nodejs.org/api/util.html#util_util_promisify_original which can be used to make the node.js API return promises. Whether you have the time and money to support non-current browsers obviously depends on your situation.
          – mikemaccana
          Jun 9 '17 at 18:28












        • IE 11 is still a current browser in 2018, sadly and it doesn't support await/async
          – Juan Mendes
          Oct 4 at 14:51










        • IE11 is not a current browser. It was released 5 years ago, has a worldwide market share of 2.5% according to caniuse, and unless someone is doubling your budget to ignore all current tech then it's not worth most people's time.
          – mikemaccana
          Oct 4 at 14:57


















        up vote
        50
        down vote













        You can use this custom library (written using Promise) to make a remote call.



        function $http(apiConfig) {
        return new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open(apiConfig.method, apiConfig.url);
        client.send();
        client.onload = function () {
        if (this.status >= 200 && this.status < 300) {
        // Performs the function "resolve" when this.status is equal to 2xx.
        // Your logic here.
        resolve(this.response);
        }
        else {
        // Performs the function "reject" when this.status is different than 2xx.
        reject(this.statusText);
        }
        };
        client.onerror = function () {
        reject(this.statusText);
        };
        });
        }


        Simple usage example:



        $http({
        method: 'get',
        url: 'google.com'
        }).then(function(response) {
        console.log(response);
        }, function(error) {
        console.log(error)
        });





        share|improve this answer






























          up vote
          47
          down vote














          Js is a single threaded.




          Browser can be divided into three parts:



          1)Event Loop



          2)Web API



          3)Event Queue



          Event Loop runs for forever i.e kind of infinite loop.Event Queue is where all your function are pushed on some event(example:click) this is one by one carried out of queue and put into Event loop which execute this function and prepares it self for next one after first one is executed.This means Execution of one function doesn't starts till the function before it in queue is executed in event loop.



          Now let us think we pushed two functions in a queue one is for getting a data from server and another utilises that data.We pushed the serverRequest() function in queue first then utiliseData() function. serverRequest function goes in event loop and makes a call to server as we never know how much time it will take to get data from server
          so this process is expected to take time and so we busy our event loop thus hanging our page, that's where Web API come into role it take this function from event loop and deals with server making event loop free so that we can execute next function from queue.The next function in queue is utiliseData() which goes in loop but because of no data available it goes waste and execution of next function continues till end of the queue.(This is called Async calling i.e we can do something else till we get data)



          Let suppose our serverRequest() function had a return statement in a code, when we get back data from server Web API will push it in queue at the end of queue.
          As it get pushed at end in queue we cannot utilise its data as there is no function left in our queue to utilise this data.Thus it is not possible to return something from Async Call.



          Thus Solution to this is callback or promise.



          A Image from one of the answers here, Correctly explains callback use...
          We give our function(function utilising data returned from server) to function calling server.



          CallBack



           function doAjax(callbackFunc, method, url) {
          var xmlHttpReq = new XMLHttpRequest();
          xmlHttpReq.open(method, url);
          xmlHttpReq.onreadystatechange = function() {

          if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
          callbackFunc(xmlHttpReq.responseText);
          }


          }
          xmlHttpReq.send(null);

          }


          In my Code it is called as



          function loadMyJson(categoryValue){
          if(categoryValue==="veg")
          doAjax(print,"GET","http://localhost:3004/vegetables");
          else if(categoryValue==="fruits")
          doAjax(print,"GET","http://localhost:3004/fruits");
          else
          console.log("Data not found");
          }


          Read here for new methods in ECMA(2016/17) for making async call(@Felix Kling Answer on Top)
          https://stackoverflow.com/a/14220323/7579856






          share|improve this answer























          • for nice picture +1
            – Kamil Kiełczewski
            Dec 3 at 18:12


















          up vote
          45
          down vote













          Another solution is to execute code via sequential executor nsynjs.



          If underlying function is promisified



          nsynjs will evaluate all promises sequentially, and put promise result into data property:






          function synchronousCode() {

          var getURL = function(url) {
          return window.fetch(url).data.text().data;
          };

          var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
          console.log('received bytes:',getURL(url).length);

          };

          nsynjs.run(synchronousCode,{},function(){
          console.log('synchronousCode done');
          });

          <script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>





          If underlying function is not promisified



          Step 1. Wrap function with callback into nsynjs-aware wrapper (if it has promisified version, you can skip this test):



          var ajaxGet = function (ctx,url) {
          var res = {};
          var ex;
          $.ajax(url)
          .done(function (data) {
          res.data = data;
          })
          .fail(function(e) {
          ex = e;
          })
          .always(function() {
          ctx.resume(ex);
          });
          return res;
          };
          ajaxGet.nsynjsHasCallback = true;


          Step 2. Put synchronous logic into function:



          function process() {
          console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
          }


          Step 3. Run function in synchronous manner via nnsynjs:



          nsynjs.run(process,this,function () {
          console.log("synchronous function finished");
          });


          Nsynjs will evaluate all operators and expressions step-by-step, pausing execution in case if result of some slow function is not ready.



          More examples here: https://github.com/amaksr/nsynjs/tree/master/examples






          share|improve this answer



















          • 1




            This is interesting. I like how it allows to code async calls the way you'd do it in other languages. But technically it's not real JavaScript?
            – J Morris
            Jun 16 '17 at 23:55


















          up vote
          35
          down vote













          It's a very common issue we face while struggling with the 'mysteries' of JavaScript. Let me try demystifying this mystery today.



          Let's start with a simple JavaScript function:



          function foo(){
          // do something
          return 'wohoo';
          }

          let bar = foo(); // bar is 'wohoo' here


          That's a simple synchronous function call (where each line of code is 'finished with its job' before the next one in sequence), and the result is same as expected.



          Now let's add a bit of twist, by introducing little delay in our function, so that all lines of code are not 'finished' in sequence. Thus, it will emulate the asynchronous behavior of function :



          function foo(){
          setTimeout( ()=>{
          return 'wohoo';
          }, 1000 )
          }

          let bar = foo() // bar is undefined here


          So there you go, that delay just broke the functionality we expected! But what exactly happened ? Well, it's actually pretty logical if you look at the code. the function foo(), upon execution, returns nothing (thus returned value is undefined), but it does start a timer, which executes a function after 1s to return 'wohoo'. But as you can see, the value that's assigned to bar is the immediately returned stuff from foo(), not anything else that comes later.



          So, how do we tackle this issue?



          Let's ask our function for a PROMISE.
          Promise is really about what it means : it means that the function guarantees you to provide with any output it gets in future. so let's see it in action for our little problem above :



          function foo(){
          return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
          setTimeout ( function(){
          // promise is RESOLVED , when execution reaches this line of code
          resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
          }, 1000 )
          })
          }

          let bar ;
          foo().then( res => {
          bar = res;
          console.log(bar) // will print 'wohoo'
          });


          Thus, the summary is - to tackle the asynchronous functions like ajax based calls etc., you can use a promise to resolve the value (which you intend to return). Thus, in short you resolve value instead of returning, in asynchronous functions.



          UPDATE (Promises with async/await)



          Apart from using then/catch to work with promises, there exists one more approach. The idea is to recognize an asynchronous function and then wait for the promises to resolve, before moving to the next line of code. It's still just the promises under the hood, but with a different syntactical approach. To make things clearer, you can find a comparison below:



          then/catch version:



          function fetchUsers(){
          let users = ;
          getUsers()
          .then(_users => users = _users)
          .catch(err =>{
          throw err
          })
          return users;
          }


          async/await version:



            async function fetchUsers(){
          try{
          let users = await getUsers()
          return users;
          }
          catch(err){
          throw err;
          }
          }





          share|improve this answer























          • is this still considered the best way to return a value from a promise or async/await?
            – edwardsmarkf
            Sep 26 at 20:58










          • @edwardsmarkf Personally I don't think there's a best way as such. I use promises with then/catch , async/await as well as generators for async portions of my code. It largely depends on the context of usage.
            – Anish K.
            Oct 3 at 16:12


















          up vote
          31
          down vote













          Here are some approaches to work with asynchronous requests:




          1. Browser Promise object


          2. Q - A promise library for JavaScript

          3. A+ Promises.js

          4. jQuery deferred

          5. XMLHttpRequest API

          6. Using callback concept - As implementation in first answer


          Example: jQuery deferred implementation to work with multiple requests






          var App = App || {};

          App = {
          getDataFromServer: function(){

          var self = this,
          deferred = $.Deferred(),
          requests = ;

          requests.push($.getJSON('request/ajax/url/1'));
          requests.push($.getJSON('request/ajax/url/2'));

          $.when.apply(jQuery, requests).done(function(xhrResponse) {
          return deferred.resolve(xhrResponse.result);
          });
          return deferred;
          },

          init: function(){

          this.getDataFromServer().done(_.bind(function(resp1, resp2) {

          // Do the operations which you wanted to do when you
          // get a response from Ajax, for example, log response.
          }, this));
          }
          };
          App.init();








          share|improve this answer






























            up vote
            30
            down vote













            ECMAScript 6 has 'generators' which allow you to easily program in an asynchronous style.



            function* myGenerator() {
            const callback = yield;
            let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
            console.log("response is:", response);

            // examples of other things you can do
            yield setTimeout(callback, 1000);
            console.log("it delayed for 1000ms");
            while (response.statusText === "error") {
            [response] = yield* anotherGenerator();
            }
            }


            To run the above code you do this:



            const gen = myGenerator(); // Create generator
            gen.next(); // Start it
            gen.next((...args) => gen.next([...args])); // Set its callback function


            If you need to target browsers that don't support ES6 you can run the code through Babel or closure-compiler to generate ECMAScript 5.



            The callback ...args are wrapped in an array and destructured when you read them so that the pattern can cope with callbacks that have multiple arguments. For example with node fs:



            const [err, data] = yield fs.readFile(filePath, "utf-8", callback);





            share|improve this answer



















            • 4




              I would be interested to know why this is down-voted. It seems a good simple answer that has not been previously given.
              – James
              Feb 17 at 17:49










            • People probably just assume answers at the end are repeats or spam.
              – ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000
              Mar 1 at 1:08


















            up vote
            28
            down vote













            Use a callback() function inside the foo() success.
            Try in this way. It is simple and easy to understand.  



            var lat = "";
            var lon = "";
            function callback(data) {
            lat = data.lat;
            lon = data.lon;
            }
            function getLoc() {
            var url = "http://ip-api.com/json"
            $.getJSON(url, function(data) {
            callback(data);
            });
            }

            getLoc();





            share|improve this answer






























              up vote
              26
              down vote













              Short answer: Your foo() method returns immediately, while the $ajax() call executes asynchronously after the function returns. The problem is then how or where to store the results retrieved by the async call once it returns.



              Several solutions have been given in this thread. Perhaps the easiest way is to pass an object to the foo() method, and to store the results in a member of that object after the async call completes.



              function foo(result) {
              $.ajax({
              url: '...',
              success: function(response) {
              result.response = response; // Store the async result
              }
              });
              }

              var result = { response: null }; // Object to hold the async result
              foo(result); // Returns before the async completes


              Note that the call to foo() will still return nothing useful. However, the result of the async call will now be stored in result.response.






              share|improve this answer

















              • 11




                While this works, it's not really better than assigning to a global variable.
                – Felix Kling
                Sep 23 '15 at 22:53


















              up vote
              20
              down vote













              Of course there are many approaches like synchronous request, promise, but from my experience I think you should use the callback approach. It's natural to asynchronous behavior of Javascript.
              So, your code snippet can be rewrite a little different:



              function foo() {
              var result;

              $.ajax({
              url: '...',
              success: function(response) {
              myCallback(response);
              }
              });

              return result;
              }

              function myCallback(response) {
              // Does something.
              }





              share|improve this answer



















              • 4




                There's nothing inherently asynchronous about callbacks or JavaScript.
                – Aluan Haddad
                Mar 18 at 19:48


















              up vote
              20
              down vote













              The question was:




              How do I return the response from an asynchronous call?




              which CAN be interpreted as:




              How to make asynchronous code look synchronous?




              The solution will be to avoid callbacks, and use a combination of Promises and async/await.



              I would like to give an example for a Ajax request.



              (Although it can be written in Javascript, I prefer to write it in Python, and compile it to Javascript using Transcrypt. It will be clear enough.)



              Lets first enable JQuery usage, to have $ available as S:



              __pragma__ ('alias', 'S', '$')


              Define a function which returns a Promise, in this case an Ajax call:



              def read(url: str):
              deferred = S.Deferred()
              S.ajax({'type': "POST", 'url': url, 'data': { },
              'success': lambda d: deferred.resolve(d),
              'error': lambda e: deferred.reject(e)
              })
              return deferred.promise()


              Use the asynchronous code as if it were synchronous:



              async def readALot():
              try:
              result1 = await read("url_1")
              result2 = await read("url_2")
              except Exception:
              console.warn("Reading a lot failed")





              share|improve this answer






























                up vote
                18
                down vote













                We find ourselves in a universe which appears to progress along a dimension we call "time". We don't really understand what time is, but we have developed abstractions and vocabulary that let us reason and talk about it: "past", "present", "future", "before", "after".



                The computer systems we build--more and more--have time as an important dimension. Certain things are set up to happen in the future. Then other things need to happen after those first things eventually occur. This is the basic notion called "asynchronicity". In our increasingly networked world, the most common case of asynchronicity is waiting for some remote system to respond to some request.



                Consider an example. You call the milkman and order some milk. When it comes, you want to put it in your coffee. You can't put the milk in your coffee right now, because it is not here yet. You have to wait for it to come before putting it in your coffee. In other words, the following won't work:



                var milk = order_milk();
                put_in_coffee(milk);


                Because JS has no way to know that it needs to wait for order_milk to finish before it executes put_in_coffee. In other words, it does not know that order_milk is asynchronous--is something that is not going to result in milk until some future time. JS, and other declarative languages execute one statement after another without waiting.



                The classic JS approach to this problem, taking advantage of the fact that JS supports functions as first-class objects which can be passed around, is to pass a function as a parameter to the asynchronous request, which it will then invoke when it has completed its task sometime in the future. That is the "callback" approach. It looks like this:



                order_milk(put_in_coffee);


                order_milk kicks off, orders the milk, then, when and only when it arrives, it invokes put_in_coffee.



                The problem with this callback approach is that it pollutes the normal semantics of a function reporting its result with return; instead, functions must not reports their results by calling a callback given as a parameter. Also, this approach can rapidly become unwieldy when dealing with longer sequences of events. For example, let's say that I want to wait for the milk to be put in the coffee, and then and only then perform a third step, namely drinking the coffee. I end up needing to write something like this:



                order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }


                where I am passing to put_in_coffee both the milk to put in it, and also the action (drink_coffee) to execute once the milk has been put in. Such code becomes hard to write, and read, and debug.



                In this case, we could rewrite the code in the question as:



                var answer;
                $.ajax('/foo.json') . done(function(response) {
                callback(response.data);
                });

                function callback(data) {
                console.log(data);
                }


                Enter promises



                This was the motivation for the notion of a "promise", which is a particular type of value which represents a future or asynchronous outcome of some sort. It can represent something that already happened, or that is going to happen in the future, or might never happen at all. Promises have a single method, named then, to which you pass an action to be executed when the outcome the promise represents has been realized.



                In the case of our milk and coffee, we design order_milk to return a promise for the milk arriving, then specify put_in_coffee as a then action, as follows:



                order_milk() . then(put_in_coffee)


                One advantage of this is that we can string these together to create sequences of future occurrences ("chaining"):



                order_milk() . then(put_in_coffee) . then(drink_coffee)


                Let's apply promises to your particular problem. We will wrap our request logic inside a function, which returns a promise:



                function get_data() {
                return $.ajax('/foo.json');
                }


                Actually, all we've done is added a return to the call to $.ajax. This works because jQuery's $.ajax already returns a kind of promise-like thing. (In practice, without getting into details, we would prefer to wrap this call so as for return a real promise, or use some alternative to $.ajax that does so.) Now, if we want to load the file and wait for it to finish and then do something, we can simply say



                get_data() . then(do_something)


                for instance,



                get_data() . 
                then(function(data) { console.log(data); });


                When using promises, we end up passing lots of functions into then, so it's often helpful to use the more compact ES6-style arrow functions:



                get_data() . 
                then(data => console.log(data));


                The async keyword



                But there's still something vaguely dissatisfying about having to write code one way if synchronous and a quite different way if asynchronous. For synchronous, we write



                a();
                b();


                but if a is asynchronous, with promises we have to write



                a() . then(b);


                Above, we said, "JS has no way to know that it needs to wait for the first call to finish before it executes the second". Wouldn't it be nice if there was some way to tell JS that? It turns out that there is--the await keyword, used inside a special type of function called an "async" function. This feature is part of the upcoming version of ES but is already available in transpilers such as Babel given the right presets. This allows us to simply write



                async function morning_routine() {
                var milk = await order_milk();
                var coffee = await put_in_coffee(milk);
                await drink(coffee);
                }


                In your case, you would be able to write something like



                async function foo() {
                data = await get_data();
                console.log(data);
                }





                share|improve this answer






























                  up vote
                  11
                  down vote













                  Using ES2017 you should have this as the function declaration



                  async function foo() {
                  var response = await $.ajax({url: '...'})
                  return response;
                  }


                  And executing it like this.



                  (async function() {
                  try {
                  var result = await foo()
                  console.log(result)
                  } catch (e) {}
                  })()


                  Or the Promise syntax



                  foo().then(response => {
                  console.log(response)

                  }).catch(error => {
                  console.log(error)

                  })





                  share|improve this answer




























                    up vote
                    10
                    down vote













                    Let's see the forest first before looking at the trees.



                    There are many informative answers with great details here, I won't repeat any of them. The key to programming in JavaScript is having first the correct mental model of overall execution.




                    1. Your entry point(s) is executed as the result of an event. For
                      example, a script tag with code is loaded into the browser.
                      (Accordingly, this is why you may need to be concerned with the
                      readiness of the page to run your code if it requires dom elements
                      to be constructed first, etc.)

                    2. Your code executes to completion--however many asynchronous calls it
                      makes--without executing any of your callbacks, including XHR
                      requests, set timeouts, dom event handlers, etc. Each of those callbacks waiting to be executed will sit in a queue, waiting their turn to be run after other events that fired have all finished execution.

                    3. Each individual callback to an XHR request, set timeout or dom
                      the event once invoked will then run to completion.


                    The good news is that if you understand this point well, you will never have to worry about race conditions. You should first and foremost thing of how you want to organize your code as essentially the response to different discrete events, and how you want to thread them together into a logical sequence. You can use promises or higher level new async/await as tools to that end, or you can roll your own.



                    But you shouldn't use any tactical tools to solve a problem until you are comfortable with the actual problem domain. Draw a map of these dependencies to know what needs to run when. Attempting an ad-hoc approach to all these callbacks is just not going to serve you well.






                    share|improve this answer






























                      up vote
                      9
                      down vote













                      Rather than throwing code at you, there are 2 concepts that are key to understanding how JS handles callbacks and asynchronicity. (is that even a word?)



                      The Event Loop and Concurrency Model



                      There are three things you need to be aware of; The queue; the event loop and the stack



                      In broad, simplistic terms, the event loop is like the project manager, it is constantly listening for any functions that want to run and communicates between the queue and the stack.



                      while (queue.waitForMessage()) {
                      queue.processNextMessage();
                      }


                      Once it receives a message to run something it adds it to the queue. The queue is the list of things that are waiting to execute (like your AJAX request). imagine it like this:



                       1. call foo.com/api/bar using foobarFunc
                      2. Go perform an infinite loop
                      ... and so on


                      When one of these messages is going to execute it pops the message from the queue and creates a stack, the stack is everything JS needs to execute to perform the instruction in the message. So in our example it's being told to call foobarFunc



                      function foobarFunc (var) {
                      console.log(anotherFunction(var));
                      }


                      So anything that foobarFunc needs to execute (in our case anotherFunction) will get pushed onto the stack. executed, and then forgotten about - the event loop will then move onto the next thing in the queue (or listen for messages)



                      The key thing here is the order of execution. That is



                      WHEN is something going to run



                      When you make a call using AJAX to an external party or run any asynchronous code (a setTimeout for example), Javascript is dependant upon a response before it can proceed.



                      The big question is when will it get the response? The answer is we don't know - so the event loop is waiting for that message to say "hey run me". If JS just waited around for that message synchronously your app would freeze and it will suck. So JS carries on executing the next item in the queue whilst waiting for the message to get added back to the queue.



                      That's why with asynchronous functionality we use things called callbacks. It's kinda like a promise quite literally. As in I promise to return something at some point jQuery uses specific callbacks called deffered.done deffered.fail and deffered.always (amongst others). You can see them all here



                      So what you need to do is pass a function that is promised to execute at some point with data that is passed to it.



                      Because a callback is not executed immediately but at a later time it's important to pass the reference to the function not it executed. so



                      function foo(bla) {
                      console.log(bla)
                      }


                      so most of the time (but not always) you'll pass foo not foo()



                      Hopefully that will make some sense. When you encounter things like this that seem confusing - i highly recommend reading the documentation fully to at least get an understanding of it. It will make you a much better developer.






                      share|improve this answer

























                        1 2
                        next


                        protected by Travis J May 30 '13 at 20:57



                        Thank you for your interest in this question.
                        Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                        Would you like to answer one of these unanswered questions instead?














                        33 Answers
                        33






                        active

                        oldest

                        votes








                        33 Answers
                        33






                        active

                        oldest

                        votes









                        active

                        oldest

                        votes






                        active

                        oldest

                        votes








                        1 2
                        next









                        up vote
                        4921
                        down vote



                        accepted
                        +150











                        → For a more general explanation of async behaviour with different examples, please see Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference



                        → If you already understand the problem, skip to the possible solutions below.




                        The problem



                        The A in Ajax stands for asynchronous . That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, $.ajax returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



                        Here is an analogy which hopefully makes the difference between synchronous and asynchronous flow clearer:



                        Synchronous



                        Imagine you make a phone call to a friend and ask him to look something up for you. Although it might take a while, you wait on the phone and stare into space, until your friend gives you the answer that you needed.



                        The same is happening when you make a function call containing "normal" code:



                        function findItem() {
                        var item;
                        while(item_not_found) {
                        // search
                        }
                        return item;
                        }

                        var item = findItem();

                        // Do something with item
                        doSomethingElse();


                        Even though findItem might take a long time to execute, any code coming after var item = findItem(); has to wait until the function returns the result.



                        Asynchronous



                        You call your friend again for the same reason. But this time you tell him that you are in a hurry and he should call you back on your mobile phone. You hang up, leave the house and do whatever you planned to do. Once your friend calls you back, you are dealing with the information he gave to you.



                        That's exactly what's happening when you do an Ajax request.



                        findItem(function(item) {
                        // Do something with item
                        });
                        doSomethingElse();


                        Instead of waiting for the response, the execution continues immediately and the statement after the Ajax call is executed. To get the response eventually, you provide a function to be called once the response was received, a callback (notice something? call back ?). Any statement coming after that call is executed before the callback is called.





                        Solution(s)



                        Embrace the asynchronous nature of JavaScript! While certain asynchronous operations provide synchronous counterparts (so does "Ajax"), it's generally discouraged to use them, especially in a browser context.



                        Why is it bad do you ask?



                        JavaScript runs in the UI thread of the browser and any long running process will lock the UI, making it unresponsive. Additionally, there is an upper limit on the execution time for JavaScript and the browser will ask the user whether to continue the execution or not.



                        All of this is really bad user experience. The user won't be able to tell whether everything is working fine or not. Furthermore, the effect will be worse for users with a slow connection.



                        In the following we will look at three different solutions that are all building on top of each other:





                        • Promises with async/await (ES2017+, available in older browsers if you use a transpiler or regenerator)


                        • Callbacks (popular in node)


                        • Promises with then() (ES2015+, available in older browsers if you use one of the many promise libraries)


                        All three are available in current browsers, and node 7+.





                        ES2017+: Promises with async/await



                        The ECMAScript version released in 2017 introduced syntax-level support for asynchronous functions. With the help of async and await, you can write asynchronous in a "synchronous style". The code is still asynchronous, but it's easier to read/understand.



                        async/await builds on top of promises: an async function always returns a promise. await "unwraps" a promise and either result in the value the promise was resolved with or throws an error if the promise was rejected.



                        Important: You can only use await inside an async function. Right now, top-level await isn't yet supported, so you might have to make an async IIFE to start an async context.



                        You can read more about async and await on MDN.



                        Here is an example that builds on top of delay above:



                        // Using 'superagent' which will return a promise.
                        var superagent = require('superagent')

                        // This is isn't declared as `async` because it already returns a promise
                        function delay() {
                        // `delay` returns a promise
                        return new Promise(function(resolve, reject) {
                        // Only `delay` is able to resolve or reject the promise
                        setTimeout(function() {
                        resolve(42); // After 3 seconds, resolve the promise with value 42
                        }, 3000);
                        });
                        }


                        async function getAllBooks() {
                        try {
                        // GET a list of book IDs of the current user
                        var bookIDs = await superagent.get('/user/books');
                        // wait for 3 seconds (just for the sake of this example)
                        await delay();
                        // GET information about each book
                        return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
                        } catch(error) {
                        // If any of the awaited promises was rejected, this catch block
                        // would catch the rejection reason
                        return null;
                        }
                        }

                        // Start an IIFE to use `await` at the top level
                        (async function(){
                        let books = await getAllBooks();
                        console.log(books);
                        })();


                        Current browser and node versions support async/await. You can also support older environments by transforming your code to ES5 with the help of regenerator (or tools that use regenerator, such as Babel).





                        Let functions accept callbacks



                        A callback is simply a function passed to another function. That other function can call the function passed whenever it is ready. In the context of an asynchronous process, the callback will be called whenever the asynchronous process is done. Usually, the result is passed to the callback.



                        In the example of the question, you can make foo accept a callback and use it as success callback. So this



                        var result = foo();
                        // Code that depends on 'result'


                        becomes



                        foo(function(result) {
                        // Code that depends on 'result'
                        });


                        Here we defined the function "inline" but you can pass any function reference:



                        function myCallback(result) {
                        // Code that depends on 'result'
                        }

                        foo(myCallback);


                        foo itself is defined as follows:



                        function foo(callback) {
                        $.ajax({
                        // ...
                        success: callback
                        });
                        }


                        callback will refer to the function we pass to foo when we call it and we simply pass it on to success. I.e. once the Ajax request is successful, $.ajax will call callback and pass the response to the callback (which can be referred to with result, since this is how we defined the callback).



                        You can also process the response before passing it to the callback:



                        function foo(callback) {
                        $.ajax({
                        // ...
                        success: function(response) {
                        // For example, filter the response
                        callback(filtered_response);
                        }
                        });
                        }


                        It's easier to write code using callbacks than it may seem. After all, JavaScript in the browser is heavily event-driven (DOM events). Receiving the Ajax response is nothing else but an event.

                        Difficulties could arise when you have to work with third-party code, but most problems can be solved by just thinking through the application flow.





                        ES2015+: Promises with then()



                        The Promise API is a new feature of ECMAScript 6 (ES2015), but it has good browser support already. There are also many libraries which implement the standard Promises API and provide additional methods to ease the use and composition of asynchronous functions (e.g. bluebird).



                        Promises are containers for future values. When the promise receives the value (it is resolved) or when it is cancelled (rejected), it notifies all of its "listeners" who want to access this value.



                        The advantage over plain callbacks is that they allow you to decouple your code and they are easier to compose.



                        Here is a simple example of using a promise:



                        function delay() {
                        // `delay` returns a promise
                        return new Promise(function(resolve, reject) {
                        // Only `delay` is able to resolve or reject the promise
                        setTimeout(function() {
                        resolve(42); // After 3 seconds, resolve the promise with value 42
                        }, 3000);
                        });
                        }

                        delay()
                        .then(function(v) { // `delay` returns a promise
                        console.log(v); // Log the value once it is resolved
                        })
                        .catch(function(v) {
                        // Or do something else if it is rejected
                        // (it would not happen in this example, since `reject` is not called).
                        });


                        Applied to our Ajax call we could use promises like this:



                        function ajax(url) {
                        return new Promise(function(resolve, reject) {
                        var xhr = new XMLHttpRequest();
                        xhr.onload = function() {
                        resolve(this.responseText);
                        };
                        xhr.onerror = reject;
                        xhr.open('GET', url);
                        xhr.send();
                        });
                        }

                        ajax("/echo/json")
                        .then(function(result) {
                        // Code depending on result
                        })
                        .catch(function() {
                        // An error occurred
                        });


                        Describing all the advantages that promise offer is beyond the scope of this answer, but if you write new code, you should seriously consider them. They provide a great abstraction and separation of your code.



                        More information about promises: HTML5 rocks - JavaScript Promises



                        Side note: jQuery's deferred objects



                        Deferred objects are jQuery's custom implementation of promises (before the Promise API was standardized). They behave almost like promises but expose a slightly different API.



                        Every Ajax method of jQuery already returns a "deferred object" (actually a promise of a deferred object) which you can just return from your function:



                        function ajax() {
                        return $.ajax(...);
                        }

                        ajax().done(function(result) {
                        // Code depending on result
                        }).fail(function() {
                        // An error occurred
                        });


                        Side note: Promise gotchas



                        Keep in mind that promises and deferred objects are just containers for a future value, they are not the value itself. For example, suppose you had the following:



                        function checkPassword() {
                        return $.ajax({
                        url: '/password',
                        data: {
                        username: $('#username').val(),
                        password: $('#password').val()
                        },
                        type: 'POST',
                        dataType: 'json'
                        });
                        }

                        if (checkPassword()) {
                        // Tell the user they're logged in
                        }


                        This code misunderstands the above asynchrony issues. Specifically, $.ajax() doesn't freeze the code while it checks the '/password' page on your server - it sends a request to the server and while it waits, immediately returns a jQuery Ajax Deferred object, not the response from the server. That means the if statement is going to always get this Deferred object, treat it as true, and proceed as though the user is logged in. Not good.



                        But the fix is easy:



                        checkPassword()
                        .done(function(r) {
                        if (r) {
                        // Tell the user they're logged in
                        } else {
                        // Tell the user their password was bad
                        }
                        })
                        .fail(function(x) {
                        // Tell the user something bad happened
                        });




                        Not recommended: Synchronous "Ajax" calls



                        As I mentioned, some(!) asynchronous operations have synchronous counterparts. I don't advocate their use, but for completeness' sake, here is how you would perform a synchronous call:



                        Without jQuery



                        If you directly use a XMLHTTPRequest object, pass false as third argument to .open.



                        jQuery



                        If you use jQuery, you can set the async option to false. Note that this option is deprecated since jQuery 1.8.
                        You can then either still use a success callback or access the responseText property of the jqXHR object:



                        function foo() {
                        var jqXHR = $.ajax({
                        //...
                        async: false
                        });
                        return jqXHR.responseText;
                        }


                        If you use any other jQuery Ajax method, such as $.get, $.getJSON, etc., you have to change it to $.ajax (since you can only pass configuration parameters to $.ajax).



                        Heads up! It is not possible to make a synchronous JSONP request. JSONP by its very nature is always asynchronous (one more reason to not even consider this option).






                        share|improve this answer



















                        • 61




                          @Pommy: If you want to use jQuery, you have to include it. Please refer to docs.jquery.com/Tutorials:Getting_Started_with_jQuery.
                          – Felix Kling
                          Jan 17 '13 at 10:47








                        • 5




                          In Solution 1, sub jQuery, I could not understand this line: If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax. (Yes, I realize my nick is a tad ironic in this case)
                          – gibberish
                          Feb 6 '13 at 21:07






                        • 23




                          @gibberish: Mmmh, I don't know how it can be made clearer. Do you see how foo is called and a function is passed to it (foo(function(result) {....});)? result is used inside this function and is the response of the Ajax request. To refer to this function, the first parameter of foo is called callback and assigned to success instead of an anonymous function. So, $.ajax will call callback when the request was successful. I tried to explain it a bit more.
                          – Felix Kling
                          Feb 6 '13 at 23:29








                        • 33




                          The Chat for this question is dead so I'm not sure where to propose outlined changes, but I propose: 1) Change the synchronous part to a simple discussion of why it's bad with no code example of how to do it. 2) Remove/merge the callback examples to only show the more flexible Deferred approach, which I think may also be a little easier to follow for those learning Javascript.
                          – Chris Moschini
                          Apr 16 '13 at 2:45






                        • 10




                          @Jessi: I think you misunderstood that part of the answer. You cannot use $.getJSON if you want the Ajax request to be synchronous. However, you should not event want the request to be synchronous, so that doesn't apply. You should be using callbacks or promises to handle the response, as it is explained earlier in the answer.
                          – Felix Kling
                          Oct 8 '15 at 17:44















                        up vote
                        4921
                        down vote



                        accepted
                        +150











                        → For a more general explanation of async behaviour with different examples, please see Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference



                        → If you already understand the problem, skip to the possible solutions below.




                        The problem



                        The A in Ajax stands for asynchronous . That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, $.ajax returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



                        Here is an analogy which hopefully makes the difference between synchronous and asynchronous flow clearer:



                        Synchronous



                        Imagine you make a phone call to a friend and ask him to look something up for you. Although it might take a while, you wait on the phone and stare into space, until your friend gives you the answer that you needed.



                        The same is happening when you make a function call containing "normal" code:



                        function findItem() {
                        var item;
                        while(item_not_found) {
                        // search
                        }
                        return item;
                        }

                        var item = findItem();

                        // Do something with item
                        doSomethingElse();


                        Even though findItem might take a long time to execute, any code coming after var item = findItem(); has to wait until the function returns the result.



                        Asynchronous



                        You call your friend again for the same reason. But this time you tell him that you are in a hurry and he should call you back on your mobile phone. You hang up, leave the house and do whatever you planned to do. Once your friend calls you back, you are dealing with the information he gave to you.



                        That's exactly what's happening when you do an Ajax request.



                        findItem(function(item) {
                        // Do something with item
                        });
                        doSomethingElse();


                        Instead of waiting for the response, the execution continues immediately and the statement after the Ajax call is executed. To get the response eventually, you provide a function to be called once the response was received, a callback (notice something? call back ?). Any statement coming after that call is executed before the callback is called.





                        Solution(s)



                        Embrace the asynchronous nature of JavaScript! While certain asynchronous operations provide synchronous counterparts (so does "Ajax"), it's generally discouraged to use them, especially in a browser context.



                        Why is it bad do you ask?



                        JavaScript runs in the UI thread of the browser and any long running process will lock the UI, making it unresponsive. Additionally, there is an upper limit on the execution time for JavaScript and the browser will ask the user whether to continue the execution or not.



                        All of this is really bad user experience. The user won't be able to tell whether everything is working fine or not. Furthermore, the effect will be worse for users with a slow connection.



                        In the following we will look at three different solutions that are all building on top of each other:





                        • Promises with async/await (ES2017+, available in older browsers if you use a transpiler or regenerator)


                        • Callbacks (popular in node)


                        • Promises with then() (ES2015+, available in older browsers if you use one of the many promise libraries)


                        All three are available in current browsers, and node 7+.





                        ES2017+: Promises with async/await



                        The ECMAScript version released in 2017 introduced syntax-level support for asynchronous functions. With the help of async and await, you can write asynchronous in a "synchronous style". The code is still asynchronous, but it's easier to read/understand.



                        async/await builds on top of promises: an async function always returns a promise. await "unwraps" a promise and either result in the value the promise was resolved with or throws an error if the promise was rejected.



                        Important: You can only use await inside an async function. Right now, top-level await isn't yet supported, so you might have to make an async IIFE to start an async context.



                        You can read more about async and await on MDN.



                        Here is an example that builds on top of delay above:



                        // Using 'superagent' which will return a promise.
                        var superagent = require('superagent')

                        // This is isn't declared as `async` because it already returns a promise
                        function delay() {
                        // `delay` returns a promise
                        return new Promise(function(resolve, reject) {
                        // Only `delay` is able to resolve or reject the promise
                        setTimeout(function() {
                        resolve(42); // After 3 seconds, resolve the promise with value 42
                        }, 3000);
                        });
                        }


                        async function getAllBooks() {
                        try {
                        // GET a list of book IDs of the current user
                        var bookIDs = await superagent.get('/user/books');
                        // wait for 3 seconds (just for the sake of this example)
                        await delay();
                        // GET information about each book
                        return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
                        } catch(error) {
                        // If any of the awaited promises was rejected, this catch block
                        // would catch the rejection reason
                        return null;
                        }
                        }

                        // Start an IIFE to use `await` at the top level
                        (async function(){
                        let books = await getAllBooks();
                        console.log(books);
                        })();


                        Current browser and node versions support async/await. You can also support older environments by transforming your code to ES5 with the help of regenerator (or tools that use regenerator, such as Babel).





                        Let functions accept callbacks



                        A callback is simply a function passed to another function. That other function can call the function passed whenever it is ready. In the context of an asynchronous process, the callback will be called whenever the asynchronous process is done. Usually, the result is passed to the callback.



                        In the example of the question, you can make foo accept a callback and use it as success callback. So this



                        var result = foo();
                        // Code that depends on 'result'


                        becomes



                        foo(function(result) {
                        // Code that depends on 'result'
                        });


                        Here we defined the function "inline" but you can pass any function reference:



                        function myCallback(result) {
                        // Code that depends on 'result'
                        }

                        foo(myCallback);


                        foo itself is defined as follows:



                        function foo(callback) {
                        $.ajax({
                        // ...
                        success: callback
                        });
                        }


                        callback will refer to the function we pass to foo when we call it and we simply pass it on to success. I.e. once the Ajax request is successful, $.ajax will call callback and pass the response to the callback (which can be referred to with result, since this is how we defined the callback).



                        You can also process the response before passing it to the callback:



                        function foo(callback) {
                        $.ajax({
                        // ...
                        success: function(response) {
                        // For example, filter the response
                        callback(filtered_response);
                        }
                        });
                        }


                        It's easier to write code using callbacks than it may seem. After all, JavaScript in the browser is heavily event-driven (DOM events). Receiving the Ajax response is nothing else but an event.

                        Difficulties could arise when you have to work with third-party code, but most problems can be solved by just thinking through the application flow.





                        ES2015+: Promises with then()



                        The Promise API is a new feature of ECMAScript 6 (ES2015), but it has good browser support already. There are also many libraries which implement the standard Promises API and provide additional methods to ease the use and composition of asynchronous functions (e.g. bluebird).



                        Promises are containers for future values. When the promise receives the value (it is resolved) or when it is cancelled (rejected), it notifies all of its "listeners" who want to access this value.



                        The advantage over plain callbacks is that they allow you to decouple your code and they are easier to compose.



                        Here is a simple example of using a promise:



                        function delay() {
                        // `delay` returns a promise
                        return new Promise(function(resolve, reject) {
                        // Only `delay` is able to resolve or reject the promise
                        setTimeout(function() {
                        resolve(42); // After 3 seconds, resolve the promise with value 42
                        }, 3000);
                        });
                        }

                        delay()
                        .then(function(v) { // `delay` returns a promise
                        console.log(v); // Log the value once it is resolved
                        })
                        .catch(function(v) {
                        // Or do something else if it is rejected
                        // (it would not happen in this example, since `reject` is not called).
                        });


                        Applied to our Ajax call we could use promises like this:



                        function ajax(url) {
                        return new Promise(function(resolve, reject) {
                        var xhr = new XMLHttpRequest();
                        xhr.onload = function() {
                        resolve(this.responseText);
                        };
                        xhr.onerror = reject;
                        xhr.open('GET', url);
                        xhr.send();
                        });
                        }

                        ajax("/echo/json")
                        .then(function(result) {
                        // Code depending on result
                        })
                        .catch(function() {
                        // An error occurred
                        });


                        Describing all the advantages that promise offer is beyond the scope of this answer, but if you write new code, you should seriously consider them. They provide a great abstraction and separation of your code.



                        More information about promises: HTML5 rocks - JavaScript Promises



                        Side note: jQuery's deferred objects



                        Deferred objects are jQuery's custom implementation of promises (before the Promise API was standardized). They behave almost like promises but expose a slightly different API.



                        Every Ajax method of jQuery already returns a "deferred object" (actually a promise of a deferred object) which you can just return from your function:



                        function ajax() {
                        return $.ajax(...);
                        }

                        ajax().done(function(result) {
                        // Code depending on result
                        }).fail(function() {
                        // An error occurred
                        });


                        Side note: Promise gotchas



                        Keep in mind that promises and deferred objects are just containers for a future value, they are not the value itself. For example, suppose you had the following:



                        function checkPassword() {
                        return $.ajax({
                        url: '/password',
                        data: {
                        username: $('#username').val(),
                        password: $('#password').val()
                        },
                        type: 'POST',
                        dataType: 'json'
                        });
                        }

                        if (checkPassword()) {
                        // Tell the user they're logged in
                        }


                        This code misunderstands the above asynchrony issues. Specifically, $.ajax() doesn't freeze the code while it checks the '/password' page on your server - it sends a request to the server and while it waits, immediately returns a jQuery Ajax Deferred object, not the response from the server. That means the if statement is going to always get this Deferred object, treat it as true, and proceed as though the user is logged in. Not good.



                        But the fix is easy:



                        checkPassword()
                        .done(function(r) {
                        if (r) {
                        // Tell the user they're logged in
                        } else {
                        // Tell the user their password was bad
                        }
                        })
                        .fail(function(x) {
                        // Tell the user something bad happened
                        });




                        Not recommended: Synchronous "Ajax" calls



                        As I mentioned, some(!) asynchronous operations have synchronous counterparts. I don't advocate their use, but for completeness' sake, here is how you would perform a synchronous call:



                        Without jQuery



                        If you directly use a XMLHTTPRequest object, pass false as third argument to .open.



                        jQuery



                        If you use jQuery, you can set the async option to false. Note that this option is deprecated since jQuery 1.8.
                        You can then either still use a success callback or access the responseText property of the jqXHR object:



                        function foo() {
                        var jqXHR = $.ajax({
                        //...
                        async: false
                        });
                        return jqXHR.responseText;
                        }


                        If you use any other jQuery Ajax method, such as $.get, $.getJSON, etc., you have to change it to $.ajax (since you can only pass configuration parameters to $.ajax).



                        Heads up! It is not possible to make a synchronous JSONP request. JSONP by its very nature is always asynchronous (one more reason to not even consider this option).






                        share|improve this answer



















                        • 61




                          @Pommy: If you want to use jQuery, you have to include it. Please refer to docs.jquery.com/Tutorials:Getting_Started_with_jQuery.
                          – Felix Kling
                          Jan 17 '13 at 10:47








                        • 5




                          In Solution 1, sub jQuery, I could not understand this line: If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax. (Yes, I realize my nick is a tad ironic in this case)
                          – gibberish
                          Feb 6 '13 at 21:07






                        • 23




                          @gibberish: Mmmh, I don't know how it can be made clearer. Do you see how foo is called and a function is passed to it (foo(function(result) {....});)? result is used inside this function and is the response of the Ajax request. To refer to this function, the first parameter of foo is called callback and assigned to success instead of an anonymous function. So, $.ajax will call callback when the request was successful. I tried to explain it a bit more.
                          – Felix Kling
                          Feb 6 '13 at 23:29








                        • 33




                          The Chat for this question is dead so I'm not sure where to propose outlined changes, but I propose: 1) Change the synchronous part to a simple discussion of why it's bad with no code example of how to do it. 2) Remove/merge the callback examples to only show the more flexible Deferred approach, which I think may also be a little easier to follow for those learning Javascript.
                          – Chris Moschini
                          Apr 16 '13 at 2:45






                        • 10




                          @Jessi: I think you misunderstood that part of the answer. You cannot use $.getJSON if you want the Ajax request to be synchronous. However, you should not event want the request to be synchronous, so that doesn't apply. You should be using callbacks or promises to handle the response, as it is explained earlier in the answer.
                          – Felix Kling
                          Oct 8 '15 at 17:44













                        up vote
                        4921
                        down vote



                        accepted
                        +150







                        up vote
                        4921
                        down vote



                        accepted
                        +150




                        +150





                        → For a more general explanation of async behaviour with different examples, please see Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference



                        → If you already understand the problem, skip to the possible solutions below.




                        The problem



                        The A in Ajax stands for asynchronous . That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, $.ajax returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



                        Here is an analogy which hopefully makes the difference between synchronous and asynchronous flow clearer:



                        Synchronous



                        Imagine you make a phone call to a friend and ask him to look something up for you. Although it might take a while, you wait on the phone and stare into space, until your friend gives you the answer that you needed.



                        The same is happening when you make a function call containing "normal" code:



                        function findItem() {
                        var item;
                        while(item_not_found) {
                        // search
                        }
                        return item;
                        }

                        var item = findItem();

                        // Do something with item
                        doSomethingElse();


                        Even though findItem might take a long time to execute, any code coming after var item = findItem(); has to wait until the function returns the result.



                        Asynchronous



                        You call your friend again for the same reason. But this time you tell him that you are in a hurry and he should call you back on your mobile phone. You hang up, leave the house and do whatever you planned to do. Once your friend calls you back, you are dealing with the information he gave to you.



                        That's exactly what's happening when you do an Ajax request.



                        findItem(function(item) {
                        // Do something with item
                        });
                        doSomethingElse();


                        Instead of waiting for the response, the execution continues immediately and the statement after the Ajax call is executed. To get the response eventually, you provide a function to be called once the response was received, a callback (notice something? call back ?). Any statement coming after that call is executed before the callback is called.





                        Solution(s)



                        Embrace the asynchronous nature of JavaScript! While certain asynchronous operations provide synchronous counterparts (so does "Ajax"), it's generally discouraged to use them, especially in a browser context.



                        Why is it bad do you ask?



                        JavaScript runs in the UI thread of the browser and any long running process will lock the UI, making it unresponsive. Additionally, there is an upper limit on the execution time for JavaScript and the browser will ask the user whether to continue the execution or not.



                        All of this is really bad user experience. The user won't be able to tell whether everything is working fine or not. Furthermore, the effect will be worse for users with a slow connection.



                        In the following we will look at three different solutions that are all building on top of each other:





                        • Promises with async/await (ES2017+, available in older browsers if you use a transpiler or regenerator)


                        • Callbacks (popular in node)


                        • Promises with then() (ES2015+, available in older browsers if you use one of the many promise libraries)


                        All three are available in current browsers, and node 7+.





                        ES2017+: Promises with async/await



                        The ECMAScript version released in 2017 introduced syntax-level support for asynchronous functions. With the help of async and await, you can write asynchronous in a "synchronous style". The code is still asynchronous, but it's easier to read/understand.



                        async/await builds on top of promises: an async function always returns a promise. await "unwraps" a promise and either result in the value the promise was resolved with or throws an error if the promise was rejected.



                        Important: You can only use await inside an async function. Right now, top-level await isn't yet supported, so you might have to make an async IIFE to start an async context.



                        You can read more about async and await on MDN.



                        Here is an example that builds on top of delay above:



                        // Using 'superagent' which will return a promise.
                        var superagent = require('superagent')

                        // This is isn't declared as `async` because it already returns a promise
                        function delay() {
                        // `delay` returns a promise
                        return new Promise(function(resolve, reject) {
                        // Only `delay` is able to resolve or reject the promise
                        setTimeout(function() {
                        resolve(42); // After 3 seconds, resolve the promise with value 42
                        }, 3000);
                        });
                        }


                        async function getAllBooks() {
                        try {
                        // GET a list of book IDs of the current user
                        var bookIDs = await superagent.get('/user/books');
                        // wait for 3 seconds (just for the sake of this example)
                        await delay();
                        // GET information about each book
                        return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
                        } catch(error) {
                        // If any of the awaited promises was rejected, this catch block
                        // would catch the rejection reason
                        return null;
                        }
                        }

                        // Start an IIFE to use `await` at the top level
                        (async function(){
                        let books = await getAllBooks();
                        console.log(books);
                        })();


                        Current browser and node versions support async/await. You can also support older environments by transforming your code to ES5 with the help of regenerator (or tools that use regenerator, such as Babel).





                        Let functions accept callbacks



                        A callback is simply a function passed to another function. That other function can call the function passed whenever it is ready. In the context of an asynchronous process, the callback will be called whenever the asynchronous process is done. Usually, the result is passed to the callback.



                        In the example of the question, you can make foo accept a callback and use it as success callback. So this



                        var result = foo();
                        // Code that depends on 'result'


                        becomes



                        foo(function(result) {
                        // Code that depends on 'result'
                        });


                        Here we defined the function "inline" but you can pass any function reference:



                        function myCallback(result) {
                        // Code that depends on 'result'
                        }

                        foo(myCallback);


                        foo itself is defined as follows:



                        function foo(callback) {
                        $.ajax({
                        // ...
                        success: callback
                        });
                        }


                        callback will refer to the function we pass to foo when we call it and we simply pass it on to success. I.e. once the Ajax request is successful, $.ajax will call callback and pass the response to the callback (which can be referred to with result, since this is how we defined the callback).



                        You can also process the response before passing it to the callback:



                        function foo(callback) {
                        $.ajax({
                        // ...
                        success: function(response) {
                        // For example, filter the response
                        callback(filtered_response);
                        }
                        });
                        }


                        It's easier to write code using callbacks than it may seem. After all, JavaScript in the browser is heavily event-driven (DOM events). Receiving the Ajax response is nothing else but an event.

                        Difficulties could arise when you have to work with third-party code, but most problems can be solved by just thinking through the application flow.





                        ES2015+: Promises with then()



                        The Promise API is a new feature of ECMAScript 6 (ES2015), but it has good browser support already. There are also many libraries which implement the standard Promises API and provide additional methods to ease the use and composition of asynchronous functions (e.g. bluebird).



                        Promises are containers for future values. When the promise receives the value (it is resolved) or when it is cancelled (rejected), it notifies all of its "listeners" who want to access this value.



                        The advantage over plain callbacks is that they allow you to decouple your code and they are easier to compose.



                        Here is a simple example of using a promise:



                        function delay() {
                        // `delay` returns a promise
                        return new Promise(function(resolve, reject) {
                        // Only `delay` is able to resolve or reject the promise
                        setTimeout(function() {
                        resolve(42); // After 3 seconds, resolve the promise with value 42
                        }, 3000);
                        });
                        }

                        delay()
                        .then(function(v) { // `delay` returns a promise
                        console.log(v); // Log the value once it is resolved
                        })
                        .catch(function(v) {
                        // Or do something else if it is rejected
                        // (it would not happen in this example, since `reject` is not called).
                        });


                        Applied to our Ajax call we could use promises like this:



                        function ajax(url) {
                        return new Promise(function(resolve, reject) {
                        var xhr = new XMLHttpRequest();
                        xhr.onload = function() {
                        resolve(this.responseText);
                        };
                        xhr.onerror = reject;
                        xhr.open('GET', url);
                        xhr.send();
                        });
                        }

                        ajax("/echo/json")
                        .then(function(result) {
                        // Code depending on result
                        })
                        .catch(function() {
                        // An error occurred
                        });


                        Describing all the advantages that promise offer is beyond the scope of this answer, but if you write new code, you should seriously consider them. They provide a great abstraction and separation of your code.



                        More information about promises: HTML5 rocks - JavaScript Promises



                        Side note: jQuery's deferred objects



                        Deferred objects are jQuery's custom implementation of promises (before the Promise API was standardized). They behave almost like promises but expose a slightly different API.



                        Every Ajax method of jQuery already returns a "deferred object" (actually a promise of a deferred object) which you can just return from your function:



                        function ajax() {
                        return $.ajax(...);
                        }

                        ajax().done(function(result) {
                        // Code depending on result
                        }).fail(function() {
                        // An error occurred
                        });


                        Side note: Promise gotchas



                        Keep in mind that promises and deferred objects are just containers for a future value, they are not the value itself. For example, suppose you had the following:



                        function checkPassword() {
                        return $.ajax({
                        url: '/password',
                        data: {
                        username: $('#username').val(),
                        password: $('#password').val()
                        },
                        type: 'POST',
                        dataType: 'json'
                        });
                        }

                        if (checkPassword()) {
                        // Tell the user they're logged in
                        }


                        This code misunderstands the above asynchrony issues. Specifically, $.ajax() doesn't freeze the code while it checks the '/password' page on your server - it sends a request to the server and while it waits, immediately returns a jQuery Ajax Deferred object, not the response from the server. That means the if statement is going to always get this Deferred object, treat it as true, and proceed as though the user is logged in. Not good.



                        But the fix is easy:



                        checkPassword()
                        .done(function(r) {
                        if (r) {
                        // Tell the user they're logged in
                        } else {
                        // Tell the user their password was bad
                        }
                        })
                        .fail(function(x) {
                        // Tell the user something bad happened
                        });




                        Not recommended: Synchronous "Ajax" calls



                        As I mentioned, some(!) asynchronous operations have synchronous counterparts. I don't advocate their use, but for completeness' sake, here is how you would perform a synchronous call:



                        Without jQuery



                        If you directly use a XMLHTTPRequest object, pass false as third argument to .open.



                        jQuery



                        If you use jQuery, you can set the async option to false. Note that this option is deprecated since jQuery 1.8.
                        You can then either still use a success callback or access the responseText property of the jqXHR object:



                        function foo() {
                        var jqXHR = $.ajax({
                        //...
                        async: false
                        });
                        return jqXHR.responseText;
                        }


                        If you use any other jQuery Ajax method, such as $.get, $.getJSON, etc., you have to change it to $.ajax (since you can only pass configuration parameters to $.ajax).



                        Heads up! It is not possible to make a synchronous JSONP request. JSONP by its very nature is always asynchronous (one more reason to not even consider this option).






                        share|improve this answer















                        → For a more general explanation of async behaviour with different examples, please see Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference



                        → If you already understand the problem, skip to the possible solutions below.




                        The problem



                        The A in Ajax stands for asynchronous . That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, $.ajax returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



                        Here is an analogy which hopefully makes the difference between synchronous and asynchronous flow clearer:



                        Synchronous



                        Imagine you make a phone call to a friend and ask him to look something up for you. Although it might take a while, you wait on the phone and stare into space, until your friend gives you the answer that you needed.



                        The same is happening when you make a function call containing "normal" code:



                        function findItem() {
                        var item;
                        while(item_not_found) {
                        // search
                        }
                        return item;
                        }

                        var item = findItem();

                        // Do something with item
                        doSomethingElse();


                        Even though findItem might take a long time to execute, any code coming after var item = findItem(); has to wait until the function returns the result.



                        Asynchronous



                        You call your friend again for the same reason. But this time you tell him that you are in a hurry and he should call you back on your mobile phone. You hang up, leave the house and do whatever you planned to do. Once your friend calls you back, you are dealing with the information he gave to you.



                        That's exactly what's happening when you do an Ajax request.



                        findItem(function(item) {
                        // Do something with item
                        });
                        doSomethingElse();


                        Instead of waiting for the response, the execution continues immediately and the statement after the Ajax call is executed. To get the response eventually, you provide a function to be called once the response was received, a callback (notice something? call back ?). Any statement coming after that call is executed before the callback is called.





                        Solution(s)



                        Embrace the asynchronous nature of JavaScript! While certain asynchronous operations provide synchronous counterparts (so does "Ajax"), it's generally discouraged to use them, especially in a browser context.



                        Why is it bad do you ask?



                        JavaScript runs in the UI thread of the browser and any long running process will lock the UI, making it unresponsive. Additionally, there is an upper limit on the execution time for JavaScript and the browser will ask the user whether to continue the execution or not.



                        All of this is really bad user experience. The user won't be able to tell whether everything is working fine or not. Furthermore, the effect will be worse for users with a slow connection.



                        In the following we will look at three different solutions that are all building on top of each other:





                        • Promises with async/await (ES2017+, available in older browsers if you use a transpiler or regenerator)


                        • Callbacks (popular in node)


                        • Promises with then() (ES2015+, available in older browsers if you use one of the many promise libraries)


                        All three are available in current browsers, and node 7+.





                        ES2017+: Promises with async/await



                        The ECMAScript version released in 2017 introduced syntax-level support for asynchronous functions. With the help of async and await, you can write asynchronous in a "synchronous style". The code is still asynchronous, but it's easier to read/understand.



                        async/await builds on top of promises: an async function always returns a promise. await "unwraps" a promise and either result in the value the promise was resolved with or throws an error if the promise was rejected.



                        Important: You can only use await inside an async function. Right now, top-level await isn't yet supported, so you might have to make an async IIFE to start an async context.



                        You can read more about async and await on MDN.



                        Here is an example that builds on top of delay above:



                        // Using 'superagent' which will return a promise.
                        var superagent = require('superagent')

                        // This is isn't declared as `async` because it already returns a promise
                        function delay() {
                        // `delay` returns a promise
                        return new Promise(function(resolve, reject) {
                        // Only `delay` is able to resolve or reject the promise
                        setTimeout(function() {
                        resolve(42); // After 3 seconds, resolve the promise with value 42
                        }, 3000);
                        });
                        }


                        async function getAllBooks() {
                        try {
                        // GET a list of book IDs of the current user
                        var bookIDs = await superagent.get('/user/books');
                        // wait for 3 seconds (just for the sake of this example)
                        await delay();
                        // GET information about each book
                        return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
                        } catch(error) {
                        // If any of the awaited promises was rejected, this catch block
                        // would catch the rejection reason
                        return null;
                        }
                        }

                        // Start an IIFE to use `await` at the top level
                        (async function(){
                        let books = await getAllBooks();
                        console.log(books);
                        })();


                        Current browser and node versions support async/await. You can also support older environments by transforming your code to ES5 with the help of regenerator (or tools that use regenerator, such as Babel).





                        Let functions accept callbacks



                        A callback is simply a function passed to another function. That other function can call the function passed whenever it is ready. In the context of an asynchronous process, the callback will be called whenever the asynchronous process is done. Usually, the result is passed to the callback.



                        In the example of the question, you can make foo accept a callback and use it as success callback. So this



                        var result = foo();
                        // Code that depends on 'result'


                        becomes



                        foo(function(result) {
                        // Code that depends on 'result'
                        });


                        Here we defined the function "inline" but you can pass any function reference:



                        function myCallback(result) {
                        // Code that depends on 'result'
                        }

                        foo(myCallback);


                        foo itself is defined as follows:



                        function foo(callback) {
                        $.ajax({
                        // ...
                        success: callback
                        });
                        }


                        callback will refer to the function we pass to foo when we call it and we simply pass it on to success. I.e. once the Ajax request is successful, $.ajax will call callback and pass the response to the callback (which can be referred to with result, since this is how we defined the callback).



                        You can also process the response before passing it to the callback:



                        function foo(callback) {
                        $.ajax({
                        // ...
                        success: function(response) {
                        // For example, filter the response
                        callback(filtered_response);
                        }
                        });
                        }


                        It's easier to write code using callbacks than it may seem. After all, JavaScript in the browser is heavily event-driven (DOM events). Receiving the Ajax response is nothing else but an event.

                        Difficulties could arise when you have to work with third-party code, but most problems can be solved by just thinking through the application flow.





                        ES2015+: Promises with then()



                        The Promise API is a new feature of ECMAScript 6 (ES2015), but it has good browser support already. There are also many libraries which implement the standard Promises API and provide additional methods to ease the use and composition of asynchronous functions (e.g. bluebird).



                        Promises are containers for future values. When the promise receives the value (it is resolved) or when it is cancelled (rejected), it notifies all of its "listeners" who want to access this value.



                        The advantage over plain callbacks is that they allow you to decouple your code and they are easier to compose.



                        Here is a simple example of using a promise:



                        function delay() {
                        // `delay` returns a promise
                        return new Promise(function(resolve, reject) {
                        // Only `delay` is able to resolve or reject the promise
                        setTimeout(function() {
                        resolve(42); // After 3 seconds, resolve the promise with value 42
                        }, 3000);
                        });
                        }

                        delay()
                        .then(function(v) { // `delay` returns a promise
                        console.log(v); // Log the value once it is resolved
                        })
                        .catch(function(v) {
                        // Or do something else if it is rejected
                        // (it would not happen in this example, since `reject` is not called).
                        });


                        Applied to our Ajax call we could use promises like this:



                        function ajax(url) {
                        return new Promise(function(resolve, reject) {
                        var xhr = new XMLHttpRequest();
                        xhr.onload = function() {
                        resolve(this.responseText);
                        };
                        xhr.onerror = reject;
                        xhr.open('GET', url);
                        xhr.send();
                        });
                        }

                        ajax("/echo/json")
                        .then(function(result) {
                        // Code depending on result
                        })
                        .catch(function() {
                        // An error occurred
                        });


                        Describing all the advantages that promise offer is beyond the scope of this answer, but if you write new code, you should seriously consider them. They provide a great abstraction and separation of your code.



                        More information about promises: HTML5 rocks - JavaScript Promises



                        Side note: jQuery's deferred objects



                        Deferred objects are jQuery's custom implementation of promises (before the Promise API was standardized). They behave almost like promises but expose a slightly different API.



                        Every Ajax method of jQuery already returns a "deferred object" (actually a promise of a deferred object) which you can just return from your function:



                        function ajax() {
                        return $.ajax(...);
                        }

                        ajax().done(function(result) {
                        // Code depending on result
                        }).fail(function() {
                        // An error occurred
                        });


                        Side note: Promise gotchas



                        Keep in mind that promises and deferred objects are just containers for a future value, they are not the value itself. For example, suppose you had the following:



                        function checkPassword() {
                        return $.ajax({
                        url: '/password',
                        data: {
                        username: $('#username').val(),
                        password: $('#password').val()
                        },
                        type: 'POST',
                        dataType: 'json'
                        });
                        }

                        if (checkPassword()) {
                        // Tell the user they're logged in
                        }


                        This code misunderstands the above asynchrony issues. Specifically, $.ajax() doesn't freeze the code while it checks the '/password' page on your server - it sends a request to the server and while it waits, immediately returns a jQuery Ajax Deferred object, not the response from the server. That means the if statement is going to always get this Deferred object, treat it as true, and proceed as though the user is logged in. Not good.



                        But the fix is easy:



                        checkPassword()
                        .done(function(r) {
                        if (r) {
                        // Tell the user they're logged in
                        } else {
                        // Tell the user their password was bad
                        }
                        })
                        .fail(function(x) {
                        // Tell the user something bad happened
                        });




                        Not recommended: Synchronous "Ajax" calls



                        As I mentioned, some(!) asynchronous operations have synchronous counterparts. I don't advocate their use, but for completeness' sake, here is how you would perform a synchronous call:



                        Without jQuery



                        If you directly use a XMLHTTPRequest object, pass false as third argument to .open.



                        jQuery



                        If you use jQuery, you can set the async option to false. Note that this option is deprecated since jQuery 1.8.
                        You can then either still use a success callback or access the responseText property of the jqXHR object:



                        function foo() {
                        var jqXHR = $.ajax({
                        //...
                        async: false
                        });
                        return jqXHR.responseText;
                        }


                        If you use any other jQuery Ajax method, such as $.get, $.getJSON, etc., you have to change it to $.ajax (since you can only pass configuration parameters to $.ajax).



                        Heads up! It is not possible to make a synchronous JSONP request. JSONP by its very nature is always asynchronous (one more reason to not even consider this option).







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Dec 11 at 16:51









                        Johan Wentholt

                        2,335618




                        2,335618










                        answered Jan 8 '13 at 17:06









                        Felix Kling

                        543k125846900




                        543k125846900








                        • 61




                          @Pommy: If you want to use jQuery, you have to include it. Please refer to docs.jquery.com/Tutorials:Getting_Started_with_jQuery.
                          – Felix Kling
                          Jan 17 '13 at 10:47








                        • 5




                          In Solution 1, sub jQuery, I could not understand this line: If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax. (Yes, I realize my nick is a tad ironic in this case)
                          – gibberish
                          Feb 6 '13 at 21:07






                        • 23




                          @gibberish: Mmmh, I don't know how it can be made clearer. Do you see how foo is called and a function is passed to it (foo(function(result) {....});)? result is used inside this function and is the response of the Ajax request. To refer to this function, the first parameter of foo is called callback and assigned to success instead of an anonymous function. So, $.ajax will call callback when the request was successful. I tried to explain it a bit more.
                          – Felix Kling
                          Feb 6 '13 at 23:29








                        • 33




                          The Chat for this question is dead so I'm not sure where to propose outlined changes, but I propose: 1) Change the synchronous part to a simple discussion of why it's bad with no code example of how to do it. 2) Remove/merge the callback examples to only show the more flexible Deferred approach, which I think may also be a little easier to follow for those learning Javascript.
                          – Chris Moschini
                          Apr 16 '13 at 2:45






                        • 10




                          @Jessi: I think you misunderstood that part of the answer. You cannot use $.getJSON if you want the Ajax request to be synchronous. However, you should not event want the request to be synchronous, so that doesn't apply. You should be using callbacks or promises to handle the response, as it is explained earlier in the answer.
                          – Felix Kling
                          Oct 8 '15 at 17:44














                        • 61




                          @Pommy: If you want to use jQuery, you have to include it. Please refer to docs.jquery.com/Tutorials:Getting_Started_with_jQuery.
                          – Felix Kling
                          Jan 17 '13 at 10:47








                        • 5




                          In Solution 1, sub jQuery, I could not understand this line: If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax. (Yes, I realize my nick is a tad ironic in this case)
                          – gibberish
                          Feb 6 '13 at 21:07






                        • 23




                          @gibberish: Mmmh, I don't know how it can be made clearer. Do you see how foo is called and a function is passed to it (foo(function(result) {....});)? result is used inside this function and is the response of the Ajax request. To refer to this function, the first parameter of foo is called callback and assigned to success instead of an anonymous function. So, $.ajax will call callback when the request was successful. I tried to explain it a bit more.
                          – Felix Kling
                          Feb 6 '13 at 23:29








                        • 33




                          The Chat for this question is dead so I'm not sure where to propose outlined changes, but I propose: 1) Change the synchronous part to a simple discussion of why it's bad with no code example of how to do it. 2) Remove/merge the callback examples to only show the more flexible Deferred approach, which I think may also be a little easier to follow for those learning Javascript.
                          – Chris Moschini
                          Apr 16 '13 at 2:45






                        • 10




                          @Jessi: I think you misunderstood that part of the answer. You cannot use $.getJSON if you want the Ajax request to be synchronous. However, you should not event want the request to be synchronous, so that doesn't apply. You should be using callbacks or promises to handle the response, as it is explained earlier in the answer.
                          – Felix Kling
                          Oct 8 '15 at 17:44








                        61




                        61




                        @Pommy: If you want to use jQuery, you have to include it. Please refer to docs.jquery.com/Tutorials:Getting_Started_with_jQuery.
                        – Felix Kling
                        Jan 17 '13 at 10:47






                        @Pommy: If you want to use jQuery, you have to include it. Please refer to docs.jquery.com/Tutorials:Getting_Started_with_jQuery.
                        – Felix Kling
                        Jan 17 '13 at 10:47






                        5




                        5




                        In Solution 1, sub jQuery, I could not understand this line: If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax. (Yes, I realize my nick is a tad ironic in this case)
                        – gibberish
                        Feb 6 '13 at 21:07




                        In Solution 1, sub jQuery, I could not understand this line: If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax. (Yes, I realize my nick is a tad ironic in this case)
                        – gibberish
                        Feb 6 '13 at 21:07




                        23




                        23




                        @gibberish: Mmmh, I don't know how it can be made clearer. Do you see how foo is called and a function is passed to it (foo(function(result) {....});)? result is used inside this function and is the response of the Ajax request. To refer to this function, the first parameter of foo is called callback and assigned to success instead of an anonymous function. So, $.ajax will call callback when the request was successful. I tried to explain it a bit more.
                        – Felix Kling
                        Feb 6 '13 at 23:29






                        @gibberish: Mmmh, I don't know how it can be made clearer. Do you see how foo is called and a function is passed to it (foo(function(result) {....});)? result is used inside this function and is the response of the Ajax request. To refer to this function, the first parameter of foo is called callback and assigned to success instead of an anonymous function. So, $.ajax will call callback when the request was successful. I tried to explain it a bit more.
                        – Felix Kling
                        Feb 6 '13 at 23:29






                        33




                        33




                        The Chat for this question is dead so I'm not sure where to propose outlined changes, but I propose: 1) Change the synchronous part to a simple discussion of why it's bad with no code example of how to do it. 2) Remove/merge the callback examples to only show the more flexible Deferred approach, which I think may also be a little easier to follow for those learning Javascript.
                        – Chris Moschini
                        Apr 16 '13 at 2:45




                        The Chat for this question is dead so I'm not sure where to propose outlined changes, but I propose: 1) Change the synchronous part to a simple discussion of why it's bad with no code example of how to do it. 2) Remove/merge the callback examples to only show the more flexible Deferred approach, which I think may also be a little easier to follow for those learning Javascript.
                        – Chris Moschini
                        Apr 16 '13 at 2:45




                        10




                        10




                        @Jessi: I think you misunderstood that part of the answer. You cannot use $.getJSON if you want the Ajax request to be synchronous. However, you should not event want the request to be synchronous, so that doesn't apply. You should be using callbacks or promises to handle the response, as it is explained earlier in the answer.
                        – Felix Kling
                        Oct 8 '15 at 17:44




                        @Jessi: I think you misunderstood that part of the answer. You cannot use $.getJSON if you want the Ajax request to be synchronous. However, you should not event want the request to be synchronous, so that doesn't apply. You should be using callbacks or promises to handle the response, as it is explained earlier in the answer.
                        – Felix Kling
                        Oct 8 '15 at 17:44












                        up vote
                        931
                        down vote













                        If you're not using jQuery in your code, this answer is for you



                        Your code should be something along the lines of this:



                        function foo() {
                        var httpRequest = new XMLHttpRequest();
                        httpRequest.open('GET', "/echo/json");
                        httpRequest.send();
                        return httpRequest.responseText;
                        }

                        var result = foo(); // always ends up being 'undefined'


                        Felix Kling did a fine job writing an answer for people using jQuery for AJAX, I've decided to provide an alternative for people who aren't.



                        (Note, for those using the new fetch API, Angular or promises I've added another answer below)





                        What you're facing



                        This is a short summary of "Explanation of the problem" from the other answer, if you're not sure after reading this, read that.



                        The A in AJAX stands for asynchronous. That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, .send returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



                        This means when you're returning, the listener you've defined did not execute yet, which means the value you're returning has not been defined.



                        Here is a simple analogy



                        function getFive(){ 
                        var a;
                        setTimeout(function(){
                        a=5;
                        },10);
                        return a;
                        }


                        (Fiddle)



                        The value of a returned is undefined since the a=5 part has not executed yet. AJAX acts like this, you're returning the value before the server got the chance to tell your browser what that value is.



                        One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed.



                        function onComplete(a){ // When the code completes, do this
                        alert(a);
                        }

                        function getFive(whenDone){
                        var a;
                        setTimeout(function(){
                        a=5;
                        whenDone(a);
                        },10);
                        }


                        This is called CPS. Basically, we're passing getFive an action to perform when it completes, we're telling our code how to react when an event completes (like our AJAX call, or in this case the timeout).



                        Usage would be:



                        getFive(onComplete);


                        Which should alert "5" to the screen. (Fiddle).



                        Possible solutions



                        There are basically two ways how to solve this:




                        1. Make the AJAX call synchronous (lets call it SJAX).

                        2. Restructure your code to work properly with callbacks.


                        1. Synchronous AJAX - Don't do it!!



                        As for synchronous AJAX, don't do it! Felix's answer raises some compelling arguments about why it's a bad idea. To sum it up, it'll freeze the user's browser until the server returns the response and create a very bad user experience. Here is another short summary taken from MDN on why:




                        XMLHttpRequest supports both synchronous and asynchronous communications. In general, however, asynchronous requests should be preferred to synchronous requests for performance reasons.



                        In short, synchronous requests block the execution of code... ...this can cause serious issues...




                        If you have to do it, you can pass a flag: Here is how:



                        var request = new XMLHttpRequest();
                        request.open('GET', 'yourURL', false); // `false` makes the request synchronous
                        request.send(null);

                        if (request.status === 200) {// That's HTTP for 'ok'
                        console.log(request.responseText);
                        }


                        2. Restructure code



                        Let your function accept a callback. In the example code foo can be made to accept a callback. We'll be telling our code how to react when foo completes.



                        So:



                        var result = foo();
                        // code that depends on `result` goes here


                        Becomes:



                        foo(function(result) {
                        // code that depends on `result`
                        });


                        Here we passed an anonymous function, but we could just as easily pass a reference to an existing function, making it look like:



                        function myHandler(result) {
                        // code that depends on `result`
                        }
                        foo(myHandler);


                        For more details on how this sort of callback design is done, check Felix's answer.



                        Now, let's define foo itself to act accordingly



                        function foo(callback) {
                        var httpRequest = new XMLHttpRequest();
                        httpRequest.onload = function(){ // when the request is loaded
                        callback(httpRequest.responseText);// we're calling our method
                        };
                        httpRequest.open('GET', "/echo/json");
                        httpRequest.send();
                        }


                        (fiddle)



                        We have now made our foo function accept an action to run when the AJAX completes successfully, we can extend this further by checking if the response status is not 200 and acting accordingly (create a fail handler and such). Effectively solving our issue.



                        If you're still having a hard time understanding this read the AJAX getting started guide at MDN.






                        share|improve this answer



















                        • 11




                          "synchronous requests block the execution of code and can leak memory and events" how can a synchronous request leak memory?
                          – Matthew G
                          Aug 16 '13 at 5:54






                        • 6




                          @MatthewG I've added a bounty on it in this question, I'll see what I can fish out. I'm removing the quote from the answer in the mean time.
                          – Benjamin Gruenbaum
                          Aug 16 '13 at 8:28






                        • 11




                          Just for the reference, XHR 2 allows us to use the onload handler, which only fires when readyState is 4. Of course, it's not supported in IE8. (iirc, may need confirmation.)
                          – Florian Margaine
                          Dec 22 '13 at 21:09








                        • 5




                          Your explanation of how to pass an anonymous function as a callback is valid but misleading. The example var bar = foo(); is asking for a variable to be defined, whereas your suggested foo(functim() {}); doesn't define bar
                          – Robbie Averill
                          Aug 7 '14 at 10:14










                        • @BenjaminGruenbaum How do I return the content of result in a variable that I can use somewhere else in my code rather than printing it with html?
                          – MorganFR
                          Nov 8 '16 at 15:39















                        up vote
                        931
                        down vote













                        If you're not using jQuery in your code, this answer is for you



                        Your code should be something along the lines of this:



                        function foo() {
                        var httpRequest = new XMLHttpRequest();
                        httpRequest.open('GET', "/echo/json");
                        httpRequest.send();
                        return httpRequest.responseText;
                        }

                        var result = foo(); // always ends up being 'undefined'


                        Felix Kling did a fine job writing an answer for people using jQuery for AJAX, I've decided to provide an alternative for people who aren't.



                        (Note, for those using the new fetch API, Angular or promises I've added another answer below)





                        What you're facing



                        This is a short summary of "Explanation of the problem" from the other answer, if you're not sure after reading this, read that.



                        The A in AJAX stands for asynchronous. That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, .send returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



                        This means when you're returning, the listener you've defined did not execute yet, which means the value you're returning has not been defined.



                        Here is a simple analogy



                        function getFive(){ 
                        var a;
                        setTimeout(function(){
                        a=5;
                        },10);
                        return a;
                        }


                        (Fiddle)



                        The value of a returned is undefined since the a=5 part has not executed yet. AJAX acts like this, you're returning the value before the server got the chance to tell your browser what that value is.



                        One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed.



                        function onComplete(a){ // When the code completes, do this
                        alert(a);
                        }

                        function getFive(whenDone){
                        var a;
                        setTimeout(function(){
                        a=5;
                        whenDone(a);
                        },10);
                        }


                        This is called CPS. Basically, we're passing getFive an action to perform when it completes, we're telling our code how to react when an event completes (like our AJAX call, or in this case the timeout).



                        Usage would be:



                        getFive(onComplete);


                        Which should alert "5" to the screen. (Fiddle).



                        Possible solutions



                        There are basically two ways how to solve this:




                        1. Make the AJAX call synchronous (lets call it SJAX).

                        2. Restructure your code to work properly with callbacks.


                        1. Synchronous AJAX - Don't do it!!



                        As for synchronous AJAX, don't do it! Felix's answer raises some compelling arguments about why it's a bad idea. To sum it up, it'll freeze the user's browser until the server returns the response and create a very bad user experience. Here is another short summary taken from MDN on why:




                        XMLHttpRequest supports both synchronous and asynchronous communications. In general, however, asynchronous requests should be preferred to synchronous requests for performance reasons.



                        In short, synchronous requests block the execution of code... ...this can cause serious issues...




                        If you have to do it, you can pass a flag: Here is how:



                        var request = new XMLHttpRequest();
                        request.open('GET', 'yourURL', false); // `false` makes the request synchronous
                        request.send(null);

                        if (request.status === 200) {// That's HTTP for 'ok'
                        console.log(request.responseText);
                        }


                        2. Restructure code



                        Let your function accept a callback. In the example code foo can be made to accept a callback. We'll be telling our code how to react when foo completes.



                        So:



                        var result = foo();
                        // code that depends on `result` goes here


                        Becomes:



                        foo(function(result) {
                        // code that depends on `result`
                        });


                        Here we passed an anonymous function, but we could just as easily pass a reference to an existing function, making it look like:



                        function myHandler(result) {
                        // code that depends on `result`
                        }
                        foo(myHandler);


                        For more details on how this sort of callback design is done, check Felix's answer.



                        Now, let's define foo itself to act accordingly



                        function foo(callback) {
                        var httpRequest = new XMLHttpRequest();
                        httpRequest.onload = function(){ // when the request is loaded
                        callback(httpRequest.responseText);// we're calling our method
                        };
                        httpRequest.open('GET', "/echo/json");
                        httpRequest.send();
                        }


                        (fiddle)



                        We have now made our foo function accept an action to run when the AJAX completes successfully, we can extend this further by checking if the response status is not 200 and acting accordingly (create a fail handler and such). Effectively solving our issue.



                        If you're still having a hard time understanding this read the AJAX getting started guide at MDN.






                        share|improve this answer



















                        • 11




                          "synchronous requests block the execution of code and can leak memory and events" how can a synchronous request leak memory?
                          – Matthew G
                          Aug 16 '13 at 5:54






                        • 6




                          @MatthewG I've added a bounty on it in this question, I'll see what I can fish out. I'm removing the quote from the answer in the mean time.
                          – Benjamin Gruenbaum
                          Aug 16 '13 at 8:28






                        • 11




                          Just for the reference, XHR 2 allows us to use the onload handler, which only fires when readyState is 4. Of course, it's not supported in IE8. (iirc, may need confirmation.)
                          – Florian Margaine
                          Dec 22 '13 at 21:09








                        • 5




                          Your explanation of how to pass an anonymous function as a callback is valid but misleading. The example var bar = foo(); is asking for a variable to be defined, whereas your suggested foo(functim() {}); doesn't define bar
                          – Robbie Averill
                          Aug 7 '14 at 10:14










                        • @BenjaminGruenbaum How do I return the content of result in a variable that I can use somewhere else in my code rather than printing it with html?
                          – MorganFR
                          Nov 8 '16 at 15:39













                        up vote
                        931
                        down vote










                        up vote
                        931
                        down vote









                        If you're not using jQuery in your code, this answer is for you



                        Your code should be something along the lines of this:



                        function foo() {
                        var httpRequest = new XMLHttpRequest();
                        httpRequest.open('GET', "/echo/json");
                        httpRequest.send();
                        return httpRequest.responseText;
                        }

                        var result = foo(); // always ends up being 'undefined'


                        Felix Kling did a fine job writing an answer for people using jQuery for AJAX, I've decided to provide an alternative for people who aren't.



                        (Note, for those using the new fetch API, Angular or promises I've added another answer below)





                        What you're facing



                        This is a short summary of "Explanation of the problem" from the other answer, if you're not sure after reading this, read that.



                        The A in AJAX stands for asynchronous. That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, .send returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



                        This means when you're returning, the listener you've defined did not execute yet, which means the value you're returning has not been defined.



                        Here is a simple analogy



                        function getFive(){ 
                        var a;
                        setTimeout(function(){
                        a=5;
                        },10);
                        return a;
                        }


                        (Fiddle)



                        The value of a returned is undefined since the a=5 part has not executed yet. AJAX acts like this, you're returning the value before the server got the chance to tell your browser what that value is.



                        One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed.



                        function onComplete(a){ // When the code completes, do this
                        alert(a);
                        }

                        function getFive(whenDone){
                        var a;
                        setTimeout(function(){
                        a=5;
                        whenDone(a);
                        },10);
                        }


                        This is called CPS. Basically, we're passing getFive an action to perform when it completes, we're telling our code how to react when an event completes (like our AJAX call, or in this case the timeout).



                        Usage would be:



                        getFive(onComplete);


                        Which should alert "5" to the screen. (Fiddle).



                        Possible solutions



                        There are basically two ways how to solve this:




                        1. Make the AJAX call synchronous (lets call it SJAX).

                        2. Restructure your code to work properly with callbacks.


                        1. Synchronous AJAX - Don't do it!!



                        As for synchronous AJAX, don't do it! Felix's answer raises some compelling arguments about why it's a bad idea. To sum it up, it'll freeze the user's browser until the server returns the response and create a very bad user experience. Here is another short summary taken from MDN on why:




                        XMLHttpRequest supports both synchronous and asynchronous communications. In general, however, asynchronous requests should be preferred to synchronous requests for performance reasons.



                        In short, synchronous requests block the execution of code... ...this can cause serious issues...




                        If you have to do it, you can pass a flag: Here is how:



                        var request = new XMLHttpRequest();
                        request.open('GET', 'yourURL', false); // `false` makes the request synchronous
                        request.send(null);

                        if (request.status === 200) {// That's HTTP for 'ok'
                        console.log(request.responseText);
                        }


                        2. Restructure code



                        Let your function accept a callback. In the example code foo can be made to accept a callback. We'll be telling our code how to react when foo completes.



                        So:



                        var result = foo();
                        // code that depends on `result` goes here


                        Becomes:



                        foo(function(result) {
                        // code that depends on `result`
                        });


                        Here we passed an anonymous function, but we could just as easily pass a reference to an existing function, making it look like:



                        function myHandler(result) {
                        // code that depends on `result`
                        }
                        foo(myHandler);


                        For more details on how this sort of callback design is done, check Felix's answer.



                        Now, let's define foo itself to act accordingly



                        function foo(callback) {
                        var httpRequest = new XMLHttpRequest();
                        httpRequest.onload = function(){ // when the request is loaded
                        callback(httpRequest.responseText);// we're calling our method
                        };
                        httpRequest.open('GET', "/echo/json");
                        httpRequest.send();
                        }


                        (fiddle)



                        We have now made our foo function accept an action to run when the AJAX completes successfully, we can extend this further by checking if the response status is not 200 and acting accordingly (create a fail handler and such). Effectively solving our issue.



                        If you're still having a hard time understanding this read the AJAX getting started guide at MDN.






                        share|improve this answer














                        If you're not using jQuery in your code, this answer is for you



                        Your code should be something along the lines of this:



                        function foo() {
                        var httpRequest = new XMLHttpRequest();
                        httpRequest.open('GET', "/echo/json");
                        httpRequest.send();
                        return httpRequest.responseText;
                        }

                        var result = foo(); // always ends up being 'undefined'


                        Felix Kling did a fine job writing an answer for people using jQuery for AJAX, I've decided to provide an alternative for people who aren't.



                        (Note, for those using the new fetch API, Angular or promises I've added another answer below)





                        What you're facing



                        This is a short summary of "Explanation of the problem" from the other answer, if you're not sure after reading this, read that.



                        The A in AJAX stands for asynchronous. That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, .send returns immediately and the next statement, return result;, is executed before the function you passed as success callback was even called.



                        This means when you're returning, the listener you've defined did not execute yet, which means the value you're returning has not been defined.



                        Here is a simple analogy



                        function getFive(){ 
                        var a;
                        setTimeout(function(){
                        a=5;
                        },10);
                        return a;
                        }


                        (Fiddle)



                        The value of a returned is undefined since the a=5 part has not executed yet. AJAX acts like this, you're returning the value before the server got the chance to tell your browser what that value is.



                        One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed.



                        function onComplete(a){ // When the code completes, do this
                        alert(a);
                        }

                        function getFive(whenDone){
                        var a;
                        setTimeout(function(){
                        a=5;
                        whenDone(a);
                        },10);
                        }


                        This is called CPS. Basically, we're passing getFive an action to perform when it completes, we're telling our code how to react when an event completes (like our AJAX call, or in this case the timeout).



                        Usage would be:



                        getFive(onComplete);


                        Which should alert "5" to the screen. (Fiddle).



                        Possible solutions



                        There are basically two ways how to solve this:




                        1. Make the AJAX call synchronous (lets call it SJAX).

                        2. Restructure your code to work properly with callbacks.


                        1. Synchronous AJAX - Don't do it!!



                        As for synchronous AJAX, don't do it! Felix's answer raises some compelling arguments about why it's a bad idea. To sum it up, it'll freeze the user's browser until the server returns the response and create a very bad user experience. Here is another short summary taken from MDN on why:




                        XMLHttpRequest supports both synchronous and asynchronous communications. In general, however, asynchronous requests should be preferred to synchronous requests for performance reasons.



                        In short, synchronous requests block the execution of code... ...this can cause serious issues...




                        If you have to do it, you can pass a flag: Here is how:



                        var request = new XMLHttpRequest();
                        request.open('GET', 'yourURL', false); // `false` makes the request synchronous
                        request.send(null);

                        if (request.status === 200) {// That's HTTP for 'ok'
                        console.log(request.responseText);
                        }


                        2. Restructure code



                        Let your function accept a callback. In the example code foo can be made to accept a callback. We'll be telling our code how to react when foo completes.



                        So:



                        var result = foo();
                        // code that depends on `result` goes here


                        Becomes:



                        foo(function(result) {
                        // code that depends on `result`
                        });


                        Here we passed an anonymous function, but we could just as easily pass a reference to an existing function, making it look like:



                        function myHandler(result) {
                        // code that depends on `result`
                        }
                        foo(myHandler);


                        For more details on how this sort of callback design is done, check Felix's answer.



                        Now, let's define foo itself to act accordingly



                        function foo(callback) {
                        var httpRequest = new XMLHttpRequest();
                        httpRequest.onload = function(){ // when the request is loaded
                        callback(httpRequest.responseText);// we're calling our method
                        };
                        httpRequest.open('GET', "/echo/json");
                        httpRequest.send();
                        }


                        (fiddle)



                        We have now made our foo function accept an action to run when the AJAX completes successfully, we can extend this further by checking if the response status is not 200 and acting accordingly (create a fail handler and such). Effectively solving our issue.



                        If you're still having a hard time understanding this read the AJAX getting started guide at MDN.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Mar 1 at 1:03









                        ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000

                        4,66841230




                        4,66841230










                        answered May 29 '13 at 23:30









                        Benjamin Gruenbaum

                        185k63398434




                        185k63398434








                        • 11




                          "synchronous requests block the execution of code and can leak memory and events" how can a synchronous request leak memory?
                          – Matthew G
                          Aug 16 '13 at 5:54






                        • 6




                          @MatthewG I've added a bounty on it in this question, I'll see what I can fish out. I'm removing the quote from the answer in the mean time.
                          – Benjamin Gruenbaum
                          Aug 16 '13 at 8:28






                        • 11




                          Just for the reference, XHR 2 allows us to use the onload handler, which only fires when readyState is 4. Of course, it's not supported in IE8. (iirc, may need confirmation.)
                          – Florian Margaine
                          Dec 22 '13 at 21:09








                        • 5




                          Your explanation of how to pass an anonymous function as a callback is valid but misleading. The example var bar = foo(); is asking for a variable to be defined, whereas your suggested foo(functim() {}); doesn't define bar
                          – Robbie Averill
                          Aug 7 '14 at 10:14










                        • @BenjaminGruenbaum How do I return the content of result in a variable that I can use somewhere else in my code rather than printing it with html?
                          – MorganFR
                          Nov 8 '16 at 15:39














                        • 11




                          "synchronous requests block the execution of code and can leak memory and events" how can a synchronous request leak memory?
                          – Matthew G
                          Aug 16 '13 at 5:54






                        • 6




                          @MatthewG I've added a bounty on it in this question, I'll see what I can fish out. I'm removing the quote from the answer in the mean time.
                          – Benjamin Gruenbaum
                          Aug 16 '13 at 8:28






                        • 11




                          Just for the reference, XHR 2 allows us to use the onload handler, which only fires when readyState is 4. Of course, it's not supported in IE8. (iirc, may need confirmation.)
                          – Florian Margaine
                          Dec 22 '13 at 21:09








                        • 5




                          Your explanation of how to pass an anonymous function as a callback is valid but misleading. The example var bar = foo(); is asking for a variable to be defined, whereas your suggested foo(functim() {}); doesn't define bar
                          – Robbie Averill
                          Aug 7 '14 at 10:14










                        • @BenjaminGruenbaum How do I return the content of result in a variable that I can use somewhere else in my code rather than printing it with html?
                          – MorganFR
                          Nov 8 '16 at 15:39








                        11




                        11




                        "synchronous requests block the execution of code and can leak memory and events" how can a synchronous request leak memory?
                        – Matthew G
                        Aug 16 '13 at 5:54




                        "synchronous requests block the execution of code and can leak memory and events" how can a synchronous request leak memory?
                        – Matthew G
                        Aug 16 '13 at 5:54




                        6




                        6




                        @MatthewG I've added a bounty on it in this question, I'll see what I can fish out. I'm removing the quote from the answer in the mean time.
                        – Benjamin Gruenbaum
                        Aug 16 '13 at 8:28




                        @MatthewG I've added a bounty on it in this question, I'll see what I can fish out. I'm removing the quote from the answer in the mean time.
                        – Benjamin Gruenbaum
                        Aug 16 '13 at 8:28




                        11




                        11




                        Just for the reference, XHR 2 allows us to use the onload handler, which only fires when readyState is 4. Of course, it's not supported in IE8. (iirc, may need confirmation.)
                        – Florian Margaine
                        Dec 22 '13 at 21:09






                        Just for the reference, XHR 2 allows us to use the onload handler, which only fires when readyState is 4. Of course, it's not supported in IE8. (iirc, may need confirmation.)
                        – Florian Margaine
                        Dec 22 '13 at 21:09






                        5




                        5




                        Your explanation of how to pass an anonymous function as a callback is valid but misleading. The example var bar = foo(); is asking for a variable to be defined, whereas your suggested foo(functim() {}); doesn't define bar
                        – Robbie Averill
                        Aug 7 '14 at 10:14




                        Your explanation of how to pass an anonymous function as a callback is valid but misleading. The example var bar = foo(); is asking for a variable to be defined, whereas your suggested foo(functim() {}); doesn't define bar
                        – Robbie Averill
                        Aug 7 '14 at 10:14












                        @BenjaminGruenbaum How do I return the content of result in a variable that I can use somewhere else in my code rather than printing it with html?
                        – MorganFR
                        Nov 8 '16 at 15:39




                        @BenjaminGruenbaum How do I return the content of result in a variable that I can use somewhere else in my code rather than printing it with html?
                        – MorganFR
                        Nov 8 '16 at 15:39










                        up vote
                        327
                        down vote













                        XMLHttpRequest 2 (first of all read the answers from Benjamin Gruenbaum & Felix Kling)



                        If you don't use jQuery and want a nice short XMLHttpRequest 2 which works on the modern browsers and also on the mobile browsers I suggest to use it this way:



                        function ajax(a, b, c){ // URL, callback, just a placeholder
                        c = new XMLHttpRequest;
                        c.open('GET', a);
                        c.onload = b;
                        c.send()
                        }


                        As you can see:




                        1. It's shorter than all other functions Listed.

                        2. The callback is set directly (so no extra unnecessary closures).

                        3. It uses the new onload (so you don't have to check for readystate && status)

                        4. There are some other situations which I don't remember that make the XMLHttpRequest 1 annoying.


                        There are two ways to get the response of this Ajax call (three using the XMLHttpRequest var name):



                        The simplest:



                        this.response


                        Or if for some reason you bind() the callback to a class:



                        e.target.response


                        Example:



                        function callback(e){
                        console.log(this.response);
                        }
                        ajax('URL', callback);


                        Or (the above one is better anonymous functions are always a problem):



                        ajax('URL', function(e){console.log(this.response)});


                        Nothing easier.



                        Now some people will probably say that it's better to use onreadystatechange or the even the XMLHttpRequest variable name. That's wrong.



                        Check out XMLHttpRequest advanced features



                        It supported all *modern browsers. And I can confirm as I'm using this approach since XMLHttpRequest 2 exists. I never had any type of problem on all browsers I use.



                        onreadystatechange is only useful if you want to get the headers on state 2.



                        Using the XMLHttpRequest variable name is another big error as you need to execute the callback inside the onload/oreadystatechange closures else you lost it.





                        Now if you want something more complex using post and FormData you can easily extend this function:



                        function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
                        c = new XMLHttpRequest;
                        c.open(e||'get', a);
                        c.onload = b;
                        c.send(d||null)
                        }


                        Again ... it's a very short function, but it does get & post.



                        Examples of usage:



                        x(url, callback); // By default it's get so no need to set
                        x(url, callback, 'post', {'key': 'val'}); // No need to set post data


                        Or pass a full form element (document.getElementsByTagName('form')[0]):



                        var fd = new FormData(form);
                        x(url, callback, 'post', fd);


                        Or set some custom values:



                        var fd = new FormData();
                        fd.append('key', 'val')
                        x(url, callback, 'post', fd);


                        As you can see I didn't implement sync... it's a bad thing.



                        Having said that ... why don't do it the easy way?





                        As mentioned in the comment the use of error && synchronous does completely break the point of the answer. Which is a nice short way to use Ajax in the proper way?



                        Error handler



                        function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
                        c = new XMLHttpRequest;
                        c.open(e||'get', a);
                        c.onload = b;
                        c.onerror = error;
                        c.send(d||null)
                        }

                        function error(e){
                        console.log('--Error--', this.type);
                        console.log('this: ', this);
                        console.log('Event: ', e)
                        }
                        function displayAjax(e){
                        console.log(e, this);
                        }
                        x('WRONGURL', displayAjax);


                        In the above script, you have an error handler which is statically defined so it does not compromise the function. The error handler can be used for other functions too.



                        But to really get out an error the only way is to write a wrong URL in which case every browser throws an error.



                        Error handlers are maybe useful if you set custom headers, set the responseType to blob array buffer or whatever...



                        Even if you pass 'POSTAPAPAP' as the method it won't throw an error.



                        Even if you pass 'fdggdgilfdghfldj' as formdata it won't throw an error.



                        In the first case the error is inside the displayAjax() under this.statusText as Method not Allowed.



                        In the second case, it simply works. You have to check at the server side if you passed the right post data.



                        cross-domain not allowed throws error automatically.



                        In the error response, there are no error codes.



                        There is only the this.type which is set to error.



                        Why add an error handler if you totally have no control over errors?
                        Most of the errors are returned inside this in the callback function displayAjax().



                        So: No need for error checks if you're able to copy and paste the URL properly. ;)



                        PS: As the first test I wrote x('x', displayAjax)..., and it totally got a response...??? So I checked the folder where the HTML is located, and there was a file called 'x.xml'. So even if you forget the extension of your file XMLHttpRequest 2 WILL FIND IT. I LOL'd





                        Read a file synchronous



                        Don't do that.



                        If you want to block the browser for a while load a nice big .txt file synchronous.



                        function omg(a, c){ // URL
                        c = new XMLHttpRequest;
                        c.open('GET', a, true);
                        c.send();
                        return c; // Or c.response
                        }


                        Now you can do



                         var res = omg('thisIsGonnaBlockThePage.txt');


                        There is no other way to do this in a non-asynchronous way. (Yeah, with setTimeout loop... but seriously?)



                        Another point is... if you work with APIs or just your own list's files or whatever you always use different functions for each request...



                        Only if you have a page where you load always the same XML/JSON or whatever you need only one function. In that case, modify a little the Ajax function and replace b with your special function.





                        The functions above are for basic use.



                        If you want to EXTEND the function...



                        Yes, you can.



                        I'm using a lot of APIs and one of the first functions I integrate into every HTML page is the first Ajax function in this answer, with GET only...



                        But you can do a lot of stuff with XMLHttpRequest 2:



                        I made a download manager (using ranges on both sides with resume, filereader, filesystem), various image resizers converters using canvas, populate web SQL databases with base64images and much more... But in these cases you should create a function only for that purpose... sometimes you need a blob, array buffers, you can set headers, override mimetype and there is a lot more...



                        But the question here is how to return an Ajax response... (I added an easy way.)






                        share|improve this answer



















                        • 11




                          While this answer is nice (And we all love XHR2 and posting file data and multipart data is totally awesome) - this shows syntactic sugar for posting XHR with JavaScript - you might want to put this in a blog post (I'd like it) or even in a library (not sure about the name x, ajax or xhr might be nicer :)). I don't see how it addresses returning the response from an AJAX call. (someone could still do var res = x("url") and not understand why it doesn't work ;)). On a side note - it would be cool if you returned c from the method so users can hook on error etc.
                          – Benjamin Gruenbaum
                          Aug 23 '13 at 5:56






                        • 21




                          2.ajax is meant to be async.. so NO var res=x('url').. That's the entire point of this question and answers :)
                          – Benjamin Gruenbaum
                          Aug 23 '13 at 17:28






                        • 2




                          why is there a 'c' parameter in the functions, if on the first line you're overwriting whatever value it had? am i missing something?
                          – Brian H.
                          Dec 21 '16 at 10:00






                        • 1




                          You can use parameters as a placeholder to avoid writing multiple times "var"
                          – cocco
                          Dec 21 '16 at 11:05






                        • 5




                          @cocco So you wrote misleading, unreadable code in a SO answer in order to save a few keystrokes? Please don't do that.
                          – stone
                          Oct 8 '17 at 6:20















                        up vote
                        327
                        down vote













                        XMLHttpRequest 2 (first of all read the answers from Benjamin Gruenbaum & Felix Kling)



                        If you don't use jQuery and want a nice short XMLHttpRequest 2 which works on the modern browsers and also on the mobile browsers I suggest to use it this way:



                        function ajax(a, b, c){ // URL, callback, just a placeholder
                        c = new XMLHttpRequest;
                        c.open('GET', a);
                        c.onload = b;
                        c.send()
                        }


                        As you can see:




                        1. It's shorter than all other functions Listed.

                        2. The callback is set directly (so no extra unnecessary closures).

                        3. It uses the new onload (so you don't have to check for readystate && status)

                        4. There are some other situations which I don't remember that make the XMLHttpRequest 1 annoying.


                        There are two ways to get the response of this Ajax call (three using the XMLHttpRequest var name):



                        The simplest:



                        this.response


                        Or if for some reason you bind() the callback to a class:



                        e.target.response


                        Example:



                        function callback(e){
                        console.log(this.response);
                        }
                        ajax('URL', callback);


                        Or (the above one is better anonymous functions are always a problem):



                        ajax('URL', function(e){console.log(this.response)});


                        Nothing easier.



                        Now some people will probably say that it's better to use onreadystatechange or the even the XMLHttpRequest variable name. That's wrong.



                        Check out XMLHttpRequest advanced features



                        It supported all *modern browsers. And I can confirm as I'm using this approach since XMLHttpRequest 2 exists. I never had any type of problem on all browsers I use.



                        onreadystatechange is only useful if you want to get the headers on state 2.



                        Using the XMLHttpRequest variable name is another big error as you need to execute the callback inside the onload/oreadystatechange closures else you lost it.





                        Now if you want something more complex using post and FormData you can easily extend this function:



                        function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
                        c = new XMLHttpRequest;
                        c.open(e||'get', a);
                        c.onload = b;
                        c.send(d||null)
                        }


                        Again ... it's a very short function, but it does get & post.



                        Examples of usage:



                        x(url, callback); // By default it's get so no need to set
                        x(url, callback, 'post', {'key': 'val'}); // No need to set post data


                        Or pass a full form element (document.getElementsByTagName('form')[0]):



                        var fd = new FormData(form);
                        x(url, callback, 'post', fd);


                        Or set some custom values:



                        var fd = new FormData();
                        fd.append('key', 'val')
                        x(url, callback, 'post', fd);


                        As you can see I didn't implement sync... it's a bad thing.



                        Having said that ... why don't do it the easy way?





                        As mentioned in the comment the use of error && synchronous does completely break the point of the answer. Which is a nice short way to use Ajax in the proper way?



                        Error handler



                        function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
                        c = new XMLHttpRequest;
                        c.open(e||'get', a);
                        c.onload = b;
                        c.onerror = error;
                        c.send(d||null)
                        }

                        function error(e){
                        console.log('--Error--', this.type);
                        console.log('this: ', this);
                        console.log('Event: ', e)
                        }
                        function displayAjax(e){
                        console.log(e, this);
                        }
                        x('WRONGURL', displayAjax);


                        In the above script, you have an error handler which is statically defined so it does not compromise the function. The error handler can be used for other functions too.



                        But to really get out an error the only way is to write a wrong URL in which case every browser throws an error.



                        Error handlers are maybe useful if you set custom headers, set the responseType to blob array buffer or whatever...



                        Even if you pass 'POSTAPAPAP' as the method it won't throw an error.



                        Even if you pass 'fdggdgilfdghfldj' as formdata it won't throw an error.



                        In the first case the error is inside the displayAjax() under this.statusText as Method not Allowed.



                        In the second case, it simply works. You have to check at the server side if you passed the right post data.



                        cross-domain not allowed throws error automatically.



                        In the error response, there are no error codes.



                        There is only the this.type which is set to error.



                        Why add an error handler if you totally have no control over errors?
                        Most of the errors are returned inside this in the callback function displayAjax().



                        So: No need for error checks if you're able to copy and paste the URL properly. ;)



                        PS: As the first test I wrote x('x', displayAjax)..., and it totally got a response...??? So I checked the folder where the HTML is located, and there was a file called 'x.xml'. So even if you forget the extension of your file XMLHttpRequest 2 WILL FIND IT. I LOL'd





                        Read a file synchronous



                        Don't do that.



                        If you want to block the browser for a while load a nice big .txt file synchronous.



                        function omg(a, c){ // URL
                        c = new XMLHttpRequest;
                        c.open('GET', a, true);
                        c.send();
                        return c; // Or c.response
                        }


                        Now you can do



                         var res = omg('thisIsGonnaBlockThePage.txt');


                        There is no other way to do this in a non-asynchronous way. (Yeah, with setTimeout loop... but seriously?)



                        Another point is... if you work with APIs or just your own list's files or whatever you always use different functions for each request...



                        Only if you have a page where you load always the same XML/JSON or whatever you need only one function. In that case, modify a little the Ajax function and replace b with your special function.





                        The functions above are for basic use.



                        If you want to EXTEND the function...



                        Yes, you can.



                        I'm using a lot of APIs and one of the first functions I integrate into every HTML page is the first Ajax function in this answer, with GET only...



                        But you can do a lot of stuff with XMLHttpRequest 2:



                        I made a download manager (using ranges on both sides with resume, filereader, filesystem), various image resizers converters using canvas, populate web SQL databases with base64images and much more... But in these cases you should create a function only for that purpose... sometimes you need a blob, array buffers, you can set headers, override mimetype and there is a lot more...



                        But the question here is how to return an Ajax response... (I added an easy way.)






                        share|improve this answer



















                        • 11




                          While this answer is nice (And we all love XHR2 and posting file data and multipart data is totally awesome) - this shows syntactic sugar for posting XHR with JavaScript - you might want to put this in a blog post (I'd like it) or even in a library (not sure about the name x, ajax or xhr might be nicer :)). I don't see how it addresses returning the response from an AJAX call. (someone could still do var res = x("url") and not understand why it doesn't work ;)). On a side note - it would be cool if you returned c from the method so users can hook on error etc.
                          – Benjamin Gruenbaum
                          Aug 23 '13 at 5:56






                        • 21




                          2.ajax is meant to be async.. so NO var res=x('url').. That's the entire point of this question and answers :)
                          – Benjamin Gruenbaum
                          Aug 23 '13 at 17:28






                        • 2




                          why is there a 'c' parameter in the functions, if on the first line you're overwriting whatever value it had? am i missing something?
                          – Brian H.
                          Dec 21 '16 at 10:00






                        • 1




                          You can use parameters as a placeholder to avoid writing multiple times "var"
                          – cocco
                          Dec 21 '16 at 11:05






                        • 5




                          @cocco So you wrote misleading, unreadable code in a SO answer in order to save a few keystrokes? Please don't do that.
                          – stone
                          Oct 8 '17 at 6:20













                        up vote
                        327
                        down vote










                        up vote
                        327
                        down vote









                        XMLHttpRequest 2 (first of all read the answers from Benjamin Gruenbaum & Felix Kling)



                        If you don't use jQuery and want a nice short XMLHttpRequest 2 which works on the modern browsers and also on the mobile browsers I suggest to use it this way:



                        function ajax(a, b, c){ // URL, callback, just a placeholder
                        c = new XMLHttpRequest;
                        c.open('GET', a);
                        c.onload = b;
                        c.send()
                        }


                        As you can see:




                        1. It's shorter than all other functions Listed.

                        2. The callback is set directly (so no extra unnecessary closures).

                        3. It uses the new onload (so you don't have to check for readystate && status)

                        4. There are some other situations which I don't remember that make the XMLHttpRequest 1 annoying.


                        There are two ways to get the response of this Ajax call (three using the XMLHttpRequest var name):



                        The simplest:



                        this.response


                        Or if for some reason you bind() the callback to a class:



                        e.target.response


                        Example:



                        function callback(e){
                        console.log(this.response);
                        }
                        ajax('URL', callback);


                        Or (the above one is better anonymous functions are always a problem):



                        ajax('URL', function(e){console.log(this.response)});


                        Nothing easier.



                        Now some people will probably say that it's better to use onreadystatechange or the even the XMLHttpRequest variable name. That's wrong.



                        Check out XMLHttpRequest advanced features



                        It supported all *modern browsers. And I can confirm as I'm using this approach since XMLHttpRequest 2 exists. I never had any type of problem on all browsers I use.



                        onreadystatechange is only useful if you want to get the headers on state 2.



                        Using the XMLHttpRequest variable name is another big error as you need to execute the callback inside the onload/oreadystatechange closures else you lost it.





                        Now if you want something more complex using post and FormData you can easily extend this function:



                        function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
                        c = new XMLHttpRequest;
                        c.open(e||'get', a);
                        c.onload = b;
                        c.send(d||null)
                        }


                        Again ... it's a very short function, but it does get & post.



                        Examples of usage:



                        x(url, callback); // By default it's get so no need to set
                        x(url, callback, 'post', {'key': 'val'}); // No need to set post data


                        Or pass a full form element (document.getElementsByTagName('form')[0]):



                        var fd = new FormData(form);
                        x(url, callback, 'post', fd);


                        Or set some custom values:



                        var fd = new FormData();
                        fd.append('key', 'val')
                        x(url, callback, 'post', fd);


                        As you can see I didn't implement sync... it's a bad thing.



                        Having said that ... why don't do it the easy way?





                        As mentioned in the comment the use of error && synchronous does completely break the point of the answer. Which is a nice short way to use Ajax in the proper way?



                        Error handler



                        function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
                        c = new XMLHttpRequest;
                        c.open(e||'get', a);
                        c.onload = b;
                        c.onerror = error;
                        c.send(d||null)
                        }

                        function error(e){
                        console.log('--Error--', this.type);
                        console.log('this: ', this);
                        console.log('Event: ', e)
                        }
                        function displayAjax(e){
                        console.log(e, this);
                        }
                        x('WRONGURL', displayAjax);


                        In the above script, you have an error handler which is statically defined so it does not compromise the function. The error handler can be used for other functions too.



                        But to really get out an error the only way is to write a wrong URL in which case every browser throws an error.



                        Error handlers are maybe useful if you set custom headers, set the responseType to blob array buffer or whatever...



                        Even if you pass 'POSTAPAPAP' as the method it won't throw an error.



                        Even if you pass 'fdggdgilfdghfldj' as formdata it won't throw an error.



                        In the first case the error is inside the displayAjax() under this.statusText as Method not Allowed.



                        In the second case, it simply works. You have to check at the server side if you passed the right post data.



                        cross-domain not allowed throws error automatically.



                        In the error response, there are no error codes.



                        There is only the this.type which is set to error.



                        Why add an error handler if you totally have no control over errors?
                        Most of the errors are returned inside this in the callback function displayAjax().



                        So: No need for error checks if you're able to copy and paste the URL properly. ;)



                        PS: As the first test I wrote x('x', displayAjax)..., and it totally got a response...??? So I checked the folder where the HTML is located, and there was a file called 'x.xml'. So even if you forget the extension of your file XMLHttpRequest 2 WILL FIND IT. I LOL'd





                        Read a file synchronous



                        Don't do that.



                        If you want to block the browser for a while load a nice big .txt file synchronous.



                        function omg(a, c){ // URL
                        c = new XMLHttpRequest;
                        c.open('GET', a, true);
                        c.send();
                        return c; // Or c.response
                        }


                        Now you can do



                         var res = omg('thisIsGonnaBlockThePage.txt');


                        There is no other way to do this in a non-asynchronous way. (Yeah, with setTimeout loop... but seriously?)



                        Another point is... if you work with APIs or just your own list's files or whatever you always use different functions for each request...



                        Only if you have a page where you load always the same XML/JSON or whatever you need only one function. In that case, modify a little the Ajax function and replace b with your special function.





                        The functions above are for basic use.



                        If you want to EXTEND the function...



                        Yes, you can.



                        I'm using a lot of APIs and one of the first functions I integrate into every HTML page is the first Ajax function in this answer, with GET only...



                        But you can do a lot of stuff with XMLHttpRequest 2:



                        I made a download manager (using ranges on both sides with resume, filereader, filesystem), various image resizers converters using canvas, populate web SQL databases with base64images and much more... But in these cases you should create a function only for that purpose... sometimes you need a blob, array buffers, you can set headers, override mimetype and there is a lot more...



                        But the question here is how to return an Ajax response... (I added an easy way.)






                        share|improve this answer














                        XMLHttpRequest 2 (first of all read the answers from Benjamin Gruenbaum & Felix Kling)



                        If you don't use jQuery and want a nice short XMLHttpRequest 2 which works on the modern browsers and also on the mobile browsers I suggest to use it this way:



                        function ajax(a, b, c){ // URL, callback, just a placeholder
                        c = new XMLHttpRequest;
                        c.open('GET', a);
                        c.onload = b;
                        c.send()
                        }


                        As you can see:




                        1. It's shorter than all other functions Listed.

                        2. The callback is set directly (so no extra unnecessary closures).

                        3. It uses the new onload (so you don't have to check for readystate && status)

                        4. There are some other situations which I don't remember that make the XMLHttpRequest 1 annoying.


                        There are two ways to get the response of this Ajax call (three using the XMLHttpRequest var name):



                        The simplest:



                        this.response


                        Or if for some reason you bind() the callback to a class:



                        e.target.response


                        Example:



                        function callback(e){
                        console.log(this.response);
                        }
                        ajax('URL', callback);


                        Or (the above one is better anonymous functions are always a problem):



                        ajax('URL', function(e){console.log(this.response)});


                        Nothing easier.



                        Now some people will probably say that it's better to use onreadystatechange or the even the XMLHttpRequest variable name. That's wrong.



                        Check out XMLHttpRequest advanced features



                        It supported all *modern browsers. And I can confirm as I'm using this approach since XMLHttpRequest 2 exists. I never had any type of problem on all browsers I use.



                        onreadystatechange is only useful if you want to get the headers on state 2.



                        Using the XMLHttpRequest variable name is another big error as you need to execute the callback inside the onload/oreadystatechange closures else you lost it.





                        Now if you want something more complex using post and FormData you can easily extend this function:



                        function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
                        c = new XMLHttpRequest;
                        c.open(e||'get', a);
                        c.onload = b;
                        c.send(d||null)
                        }


                        Again ... it's a very short function, but it does get & post.



                        Examples of usage:



                        x(url, callback); // By default it's get so no need to set
                        x(url, callback, 'post', {'key': 'val'}); // No need to set post data


                        Or pass a full form element (document.getElementsByTagName('form')[0]):



                        var fd = new FormData(form);
                        x(url, callback, 'post', fd);


                        Or set some custom values:



                        var fd = new FormData();
                        fd.append('key', 'val')
                        x(url, callback, 'post', fd);


                        As you can see I didn't implement sync... it's a bad thing.



                        Having said that ... why don't do it the easy way?





                        As mentioned in the comment the use of error && synchronous does completely break the point of the answer. Which is a nice short way to use Ajax in the proper way?



                        Error handler



                        function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
                        c = new XMLHttpRequest;
                        c.open(e||'get', a);
                        c.onload = b;
                        c.onerror = error;
                        c.send(d||null)
                        }

                        function error(e){
                        console.log('--Error--', this.type);
                        console.log('this: ', this);
                        console.log('Event: ', e)
                        }
                        function displayAjax(e){
                        console.log(e, this);
                        }
                        x('WRONGURL', displayAjax);


                        In the above script, you have an error handler which is statically defined so it does not compromise the function. The error handler can be used for other functions too.



                        But to really get out an error the only way is to write a wrong URL in which case every browser throws an error.



                        Error handlers are maybe useful if you set custom headers, set the responseType to blob array buffer or whatever...



                        Even if you pass 'POSTAPAPAP' as the method it won't throw an error.



                        Even if you pass 'fdggdgilfdghfldj' as formdata it won't throw an error.



                        In the first case the error is inside the displayAjax() under this.statusText as Method not Allowed.



                        In the second case, it simply works. You have to check at the server side if you passed the right post data.



                        cross-domain not allowed throws error automatically.



                        In the error response, there are no error codes.



                        There is only the this.type which is set to error.



                        Why add an error handler if you totally have no control over errors?
                        Most of the errors are returned inside this in the callback function displayAjax().



                        So: No need for error checks if you're able to copy and paste the URL properly. ;)



                        PS: As the first test I wrote x('x', displayAjax)..., and it totally got a response...??? So I checked the folder where the HTML is located, and there was a file called 'x.xml'. So even if you forget the extension of your file XMLHttpRequest 2 WILL FIND IT. I LOL'd





                        Read a file synchronous



                        Don't do that.



                        If you want to block the browser for a while load a nice big .txt file synchronous.



                        function omg(a, c){ // URL
                        c = new XMLHttpRequest;
                        c.open('GET', a, true);
                        c.send();
                        return c; // Or c.response
                        }


                        Now you can do



                         var res = omg('thisIsGonnaBlockThePage.txt');


                        There is no other way to do this in a non-asynchronous way. (Yeah, with setTimeout loop... but seriously?)



                        Another point is... if you work with APIs or just your own list's files or whatever you always use different functions for each request...



                        Only if you have a page where you load always the same XML/JSON or whatever you need only one function. In that case, modify a little the Ajax function and replace b with your special function.





                        The functions above are for basic use.



                        If you want to EXTEND the function...



                        Yes, you can.



                        I'm using a lot of APIs and one of the first functions I integrate into every HTML page is the first Ajax function in this answer, with GET only...



                        But you can do a lot of stuff with XMLHttpRequest 2:



                        I made a download manager (using ranges on both sides with resume, filereader, filesystem), various image resizers converters using canvas, populate web SQL databases with base64images and much more... But in these cases you should create a function only for that purpose... sometimes you need a blob, array buffers, you can set headers, override mimetype and there is a lot more...



                        But the question here is how to return an Ajax response... (I added an easy way.)







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Dec 10 at 9:08









                        Quentin

                        638k718611031




                        638k718611031










                        answered Aug 19 '13 at 8:06









                        cocco

                        12.2k64068




                        12.2k64068








                        • 11




                          While this answer is nice (And we all love XHR2 and posting file data and multipart data is totally awesome) - this shows syntactic sugar for posting XHR with JavaScript - you might want to put this in a blog post (I'd like it) or even in a library (not sure about the name x, ajax or xhr might be nicer :)). I don't see how it addresses returning the response from an AJAX call. (someone could still do var res = x("url") and not understand why it doesn't work ;)). On a side note - it would be cool if you returned c from the method so users can hook on error etc.
                          – Benjamin Gruenbaum
                          Aug 23 '13 at 5:56






                        • 21




                          2.ajax is meant to be async.. so NO var res=x('url').. That's the entire point of this question and answers :)
                          – Benjamin Gruenbaum
                          Aug 23 '13 at 17:28






                        • 2




                          why is there a 'c' parameter in the functions, if on the first line you're overwriting whatever value it had? am i missing something?
                          – Brian H.
                          Dec 21 '16 at 10:00






                        • 1




                          You can use parameters as a placeholder to avoid writing multiple times "var"
                          – cocco
                          Dec 21 '16 at 11:05






                        • 5




                          @cocco So you wrote misleading, unreadable code in a SO answer in order to save a few keystrokes? Please don't do that.
                          – stone
                          Oct 8 '17 at 6:20














                        • 11




                          While this answer is nice (And we all love XHR2 and posting file data and multipart data is totally awesome) - this shows syntactic sugar for posting XHR with JavaScript - you might want to put this in a blog post (I'd like it) or even in a library (not sure about the name x, ajax or xhr might be nicer :)). I don't see how it addresses returning the response from an AJAX call. (someone could still do var res = x("url") and not understand why it doesn't work ;)). On a side note - it would be cool if you returned c from the method so users can hook on error etc.
                          – Benjamin Gruenbaum
                          Aug 23 '13 at 5:56






                        • 21




                          2.ajax is meant to be async.. so NO var res=x('url').. That's the entire point of this question and answers :)
                          – Benjamin Gruenbaum
                          Aug 23 '13 at 17:28






                        • 2




                          why is there a 'c' parameter in the functions, if on the first line you're overwriting whatever value it had? am i missing something?
                          – Brian H.
                          Dec 21 '16 at 10:00






                        • 1




                          You can use parameters as a placeholder to avoid writing multiple times "var"
                          – cocco
                          Dec 21 '16 at 11:05






                        • 5




                          @cocco So you wrote misleading, unreadable code in a SO answer in order to save a few keystrokes? Please don't do that.
                          – stone
                          Oct 8 '17 at 6:20








                        11




                        11




                        While this answer is nice (And we all love XHR2 and posting file data and multipart data is totally awesome) - this shows syntactic sugar for posting XHR with JavaScript - you might want to put this in a blog post (I'd like it) or even in a library (not sure about the name x, ajax or xhr might be nicer :)). I don't see how it addresses returning the response from an AJAX call. (someone could still do var res = x("url") and not understand why it doesn't work ;)). On a side note - it would be cool if you returned c from the method so users can hook on error etc.
                        – Benjamin Gruenbaum
                        Aug 23 '13 at 5:56




                        While this answer is nice (And we all love XHR2 and posting file data and multipart data is totally awesome) - this shows syntactic sugar for posting XHR with JavaScript - you might want to put this in a blog post (I'd like it) or even in a library (not sure about the name x, ajax or xhr might be nicer :)). I don't see how it addresses returning the response from an AJAX call. (someone could still do var res = x("url") and not understand why it doesn't work ;)). On a side note - it would be cool if you returned c from the method so users can hook on error etc.
                        – Benjamin Gruenbaum
                        Aug 23 '13 at 5:56




                        21




                        21




                        2.ajax is meant to be async.. so NO var res=x('url').. That's the entire point of this question and answers :)
                        – Benjamin Gruenbaum
                        Aug 23 '13 at 17:28




                        2.ajax is meant to be async.. so NO var res=x('url').. That's the entire point of this question and answers :)
                        – Benjamin Gruenbaum
                        Aug 23 '13 at 17:28




                        2




                        2




                        why is there a 'c' parameter in the functions, if on the first line you're overwriting whatever value it had? am i missing something?
                        – Brian H.
                        Dec 21 '16 at 10:00




                        why is there a 'c' parameter in the functions, if on the first line you're overwriting whatever value it had? am i missing something?
                        – Brian H.
                        Dec 21 '16 at 10:00




                        1




                        1




                        You can use parameters as a placeholder to avoid writing multiple times "var"
                        – cocco
                        Dec 21 '16 at 11:05




                        You can use parameters as a placeholder to avoid writing multiple times "var"
                        – cocco
                        Dec 21 '16 at 11:05




                        5




                        5




                        @cocco So you wrote misleading, unreadable code in a SO answer in order to save a few keystrokes? Please don't do that.
                        – stone
                        Oct 8 '17 at 6:20




                        @cocco So you wrote misleading, unreadable code in a SO answer in order to save a few keystrokes? Please don't do that.
                        – stone
                        Oct 8 '17 at 6:20










                        up vote
                        264
                        down vote













                        If you're using promises, this answer is for you.



                        This means AngularJS, jQuery (with deferred), native XHR's replacement (fetch), EmberJS, BackboneJS's save or any node library that returns promises.



                        Your code should be something along the lines of this:



                        function foo() {
                        var data;
                        // or $.get(...).then, or request(...).then, or query(...).then
                        fetch("/echo/json").then(function(response){
                        data = response.json();
                        });
                        return data;
                        }

                        var result = foo(); // result is always undefined no matter what.


                        Felix Kling did a fine job writing an answer for people using jQuery with callbacks for AJAX. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.





                        The core issue



                        The JavaScript concurrency model in the browser and on the server with NodeJS/io.js is asynchronous and reactive.



                        Whenever you call a method that returns a promise, the then handlers are always executed asynchronously - that is, after the code below them that is not in a .then handler.



                        This means when you're returning data the then handler you've defined did not execute yet. This in turn means that the value you're returning has not been set to the correct value in time.



                        Here is a simple analogy for the issue:




                            function getFive(){
                        var data;
                        setTimeout(function(){ // set a timer for one second in the future
                        data = 5; // after a second, do this
                        }, 1000);
                        return data;
                        }
                        document.body.innerHTML = getFive(); // `undefined` here and not 5





                        The value of data is undefined since the data = 5 part has not executed yet. It will likely execute in a second but by that time it is irrelevant to the returned value.



                        Since the operation did not happen yet (AJAX, server call, IO, timer) you're returning the value before the request got the chance to tell your code what that value is.



                        One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed. Promises actively enable this by being temporal (time-sensitive) in nature.



                        Quick recap on promises



                        A Promise is a value over time. Promises have state, they start as pending with no value and can settle to:





                        • fulfilled meaning that the computation completed successfully.


                        • rejected meaning that the computation failed.


                        A promise can only change states once after which it will always stay at the same state forever. You can attach then handlers to promises to extract their value and handle errors. then handlers allow chaining of calls. Promises are created by using APIs that return them. For example, the more modern AJAX replacement fetch or jQuery's $.get return promises.



                        When we call .then on a promise and return something from it - we get a promise for the processed value. If we return another promise we'll get amazing things, but let's hold our horses.



                        With promises



                        Let's see how we can solve the above issue with promises. First, let's demonstrate our understanding of promise states from above by using the Promise constructor for creating a delay function:



                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }


                        Now, after we converted setTimeout to use promises, we can use then to make it count:






                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }

                        function getFive(){
                        // we're RETURNING the promise, remember, a promise is a wrapper over our value
                        return delay(100).then(function(){ // when the promise is ready
                        return 5; // return the value 5, promises are all about return values
                        })
                        }
                        // we _have_ to wrap it like this in the call site, we can't access the plain value
                        getFive().then(function(five){
                        document.body.innerHTML = five;
                        });





                        Basically, instead of returning a value which we can't do because of the concurrency model - we're returning a wrapper for a value that we can unwrap with then. It's like a box you can open with then.



                        Applying this



                        This stands the same for your original API call, you can:



                        function foo() {
                        // RETURN the promise
                        return fetch("/echo/json").then(function(response){
                        return response.json(); // process it inside the `then`
                        });
                        }

                        foo().then(function(response){
                        // access the value inside the `then`
                        })


                        So this works just as well. We've learned we can't return values from already asynchronous calls but we can use promises and chain them to perform processing. We now know how to return the response from an asynchronous call.



                        ES2015 (ES6)



                        ES6 introduces generators which are functions that can return in the middle and then resume the point they were at. This is typically useful for sequences, for example:



                        function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
                        yield 1;
                        yield 2;
                        while(true) yield 3;
                        }


                        Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility there is one particular interesting case.



                        If the sequence we're producing is a sequence of actions rather than numbers - we can pause the function whenever an action is yielded and wait for it before we resume the function. So instead of a sequence of numbers, we need a sequence of future values - that is: promises.



                        This somewhat tricky but very powerful trick lets us write asynchronous code in a synchronous manner. There are several "runners" that do this for you, writing one is a short few lines of code but is beyond the scope of this answer. I'll be using Bluebird's Promise.coroutine here, but there are other wrappers like co or Q.async.



                        var foo = coroutine(function*(){
                        var data = yield fetch("/echo/json"); // notice the yield
                        // code here only executes _after_ the request is done
                        return data.json(); // data is defined
                        });


                        This method returns a promise itself, which we can consume from other coroutines. For example:



                        var main = coroutine(function*(){
                        var bar = yield foo(); // wait our earlier coroutine, it returns a promise
                        // server call done here, code below executes when done
                        var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
                        console.log(baz); // runs after both requests done
                        });
                        main();


                        ES2016 (ES7)



                        In ES7, this is further standardized, there are several proposals right now but in all of them you can await promise. This is just "sugar" (nicer syntax) for the ES6 proposal above by adding the async and await keywords. Making the above example:



                        async function foo(){
                        var data = await fetch("/echo/json"); // notice the await
                        // code here only executes _after_ the request is done
                        return data.json(); // data is defined
                        }


                        It still returns a promise just the same :)






                        share|improve this answer



















                        • 17




                          ES 2016 looks like the final solution to this problem once and for all.
                          – ShrekOverflow
                          May 12 '15 at 16:42






                        • 10




                          The absolutely final solution, for once and for all? What about the totally absolutely final solution, for once and for all plus one?
                          – Shmiddty
                          May 13 '15 at 6:11






                        • 3




                          @recurf first of all "where the hell" is hardly appropriate for this site (kids are using it too, for one). Second of all - it's a function parameter, I could have named it anywhere else and it would work just as fine.
                          – Benjamin Gruenbaum
                          Jan 20 '17 at 0:08










                        • @TDR by awaiting with async/await or with a then
                          – Benjamin Gruenbaum
                          Jul 17 at 18:45















                        up vote
                        264
                        down vote













                        If you're using promises, this answer is for you.



                        This means AngularJS, jQuery (with deferred), native XHR's replacement (fetch), EmberJS, BackboneJS's save or any node library that returns promises.



                        Your code should be something along the lines of this:



                        function foo() {
                        var data;
                        // or $.get(...).then, or request(...).then, or query(...).then
                        fetch("/echo/json").then(function(response){
                        data = response.json();
                        });
                        return data;
                        }

                        var result = foo(); // result is always undefined no matter what.


                        Felix Kling did a fine job writing an answer for people using jQuery with callbacks for AJAX. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.





                        The core issue



                        The JavaScript concurrency model in the browser and on the server with NodeJS/io.js is asynchronous and reactive.



                        Whenever you call a method that returns a promise, the then handlers are always executed asynchronously - that is, after the code below them that is not in a .then handler.



                        This means when you're returning data the then handler you've defined did not execute yet. This in turn means that the value you're returning has not been set to the correct value in time.



                        Here is a simple analogy for the issue:




                            function getFive(){
                        var data;
                        setTimeout(function(){ // set a timer for one second in the future
                        data = 5; // after a second, do this
                        }, 1000);
                        return data;
                        }
                        document.body.innerHTML = getFive(); // `undefined` here and not 5





                        The value of data is undefined since the data = 5 part has not executed yet. It will likely execute in a second but by that time it is irrelevant to the returned value.



                        Since the operation did not happen yet (AJAX, server call, IO, timer) you're returning the value before the request got the chance to tell your code what that value is.



                        One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed. Promises actively enable this by being temporal (time-sensitive) in nature.



                        Quick recap on promises



                        A Promise is a value over time. Promises have state, they start as pending with no value and can settle to:





                        • fulfilled meaning that the computation completed successfully.


                        • rejected meaning that the computation failed.


                        A promise can only change states once after which it will always stay at the same state forever. You can attach then handlers to promises to extract their value and handle errors. then handlers allow chaining of calls. Promises are created by using APIs that return them. For example, the more modern AJAX replacement fetch or jQuery's $.get return promises.



                        When we call .then on a promise and return something from it - we get a promise for the processed value. If we return another promise we'll get amazing things, but let's hold our horses.



                        With promises



                        Let's see how we can solve the above issue with promises. First, let's demonstrate our understanding of promise states from above by using the Promise constructor for creating a delay function:



                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }


                        Now, after we converted setTimeout to use promises, we can use then to make it count:






                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }

                        function getFive(){
                        // we're RETURNING the promise, remember, a promise is a wrapper over our value
                        return delay(100).then(function(){ // when the promise is ready
                        return 5; // return the value 5, promises are all about return values
                        })
                        }
                        // we _have_ to wrap it like this in the call site, we can't access the plain value
                        getFive().then(function(five){
                        document.body.innerHTML = five;
                        });





                        Basically, instead of returning a value which we can't do because of the concurrency model - we're returning a wrapper for a value that we can unwrap with then. It's like a box you can open with then.



                        Applying this



                        This stands the same for your original API call, you can:



                        function foo() {
                        // RETURN the promise
                        return fetch("/echo/json").then(function(response){
                        return response.json(); // process it inside the `then`
                        });
                        }

                        foo().then(function(response){
                        // access the value inside the `then`
                        })


                        So this works just as well. We've learned we can't return values from already asynchronous calls but we can use promises and chain them to perform processing. We now know how to return the response from an asynchronous call.



                        ES2015 (ES6)



                        ES6 introduces generators which are functions that can return in the middle and then resume the point they were at. This is typically useful for sequences, for example:



                        function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
                        yield 1;
                        yield 2;
                        while(true) yield 3;
                        }


                        Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility there is one particular interesting case.



                        If the sequence we're producing is a sequence of actions rather than numbers - we can pause the function whenever an action is yielded and wait for it before we resume the function. So instead of a sequence of numbers, we need a sequence of future values - that is: promises.



                        This somewhat tricky but very powerful trick lets us write asynchronous code in a synchronous manner. There are several "runners" that do this for you, writing one is a short few lines of code but is beyond the scope of this answer. I'll be using Bluebird's Promise.coroutine here, but there are other wrappers like co or Q.async.



                        var foo = coroutine(function*(){
                        var data = yield fetch("/echo/json"); // notice the yield
                        // code here only executes _after_ the request is done
                        return data.json(); // data is defined
                        });


                        This method returns a promise itself, which we can consume from other coroutines. For example:



                        var main = coroutine(function*(){
                        var bar = yield foo(); // wait our earlier coroutine, it returns a promise
                        // server call done here, code below executes when done
                        var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
                        console.log(baz); // runs after both requests done
                        });
                        main();


                        ES2016 (ES7)



                        In ES7, this is further standardized, there are several proposals right now but in all of them you can await promise. This is just "sugar" (nicer syntax) for the ES6 proposal above by adding the async and await keywords. Making the above example:



                        async function foo(){
                        var data = await fetch("/echo/json"); // notice the await
                        // code here only executes _after_ the request is done
                        return data.json(); // data is defined
                        }


                        It still returns a promise just the same :)






                        share|improve this answer



















                        • 17




                          ES 2016 looks like the final solution to this problem once and for all.
                          – ShrekOverflow
                          May 12 '15 at 16:42






                        • 10




                          The absolutely final solution, for once and for all? What about the totally absolutely final solution, for once and for all plus one?
                          – Shmiddty
                          May 13 '15 at 6:11






                        • 3




                          @recurf first of all "where the hell" is hardly appropriate for this site (kids are using it too, for one). Second of all - it's a function parameter, I could have named it anywhere else and it would work just as fine.
                          – Benjamin Gruenbaum
                          Jan 20 '17 at 0:08










                        • @TDR by awaiting with async/await or with a then
                          – Benjamin Gruenbaum
                          Jul 17 at 18:45













                        up vote
                        264
                        down vote










                        up vote
                        264
                        down vote









                        If you're using promises, this answer is for you.



                        This means AngularJS, jQuery (with deferred), native XHR's replacement (fetch), EmberJS, BackboneJS's save or any node library that returns promises.



                        Your code should be something along the lines of this:



                        function foo() {
                        var data;
                        // or $.get(...).then, or request(...).then, or query(...).then
                        fetch("/echo/json").then(function(response){
                        data = response.json();
                        });
                        return data;
                        }

                        var result = foo(); // result is always undefined no matter what.


                        Felix Kling did a fine job writing an answer for people using jQuery with callbacks for AJAX. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.





                        The core issue



                        The JavaScript concurrency model in the browser and on the server with NodeJS/io.js is asynchronous and reactive.



                        Whenever you call a method that returns a promise, the then handlers are always executed asynchronously - that is, after the code below them that is not in a .then handler.



                        This means when you're returning data the then handler you've defined did not execute yet. This in turn means that the value you're returning has not been set to the correct value in time.



                        Here is a simple analogy for the issue:




                            function getFive(){
                        var data;
                        setTimeout(function(){ // set a timer for one second in the future
                        data = 5; // after a second, do this
                        }, 1000);
                        return data;
                        }
                        document.body.innerHTML = getFive(); // `undefined` here and not 5





                        The value of data is undefined since the data = 5 part has not executed yet. It will likely execute in a second but by that time it is irrelevant to the returned value.



                        Since the operation did not happen yet (AJAX, server call, IO, timer) you're returning the value before the request got the chance to tell your code what that value is.



                        One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed. Promises actively enable this by being temporal (time-sensitive) in nature.



                        Quick recap on promises



                        A Promise is a value over time. Promises have state, they start as pending with no value and can settle to:





                        • fulfilled meaning that the computation completed successfully.


                        • rejected meaning that the computation failed.


                        A promise can only change states once after which it will always stay at the same state forever. You can attach then handlers to promises to extract their value and handle errors. then handlers allow chaining of calls. Promises are created by using APIs that return them. For example, the more modern AJAX replacement fetch or jQuery's $.get return promises.



                        When we call .then on a promise and return something from it - we get a promise for the processed value. If we return another promise we'll get amazing things, but let's hold our horses.



                        With promises



                        Let's see how we can solve the above issue with promises. First, let's demonstrate our understanding of promise states from above by using the Promise constructor for creating a delay function:



                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }


                        Now, after we converted setTimeout to use promises, we can use then to make it count:






                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }

                        function getFive(){
                        // we're RETURNING the promise, remember, a promise is a wrapper over our value
                        return delay(100).then(function(){ // when the promise is ready
                        return 5; // return the value 5, promises are all about return values
                        })
                        }
                        // we _have_ to wrap it like this in the call site, we can't access the plain value
                        getFive().then(function(five){
                        document.body.innerHTML = five;
                        });





                        Basically, instead of returning a value which we can't do because of the concurrency model - we're returning a wrapper for a value that we can unwrap with then. It's like a box you can open with then.



                        Applying this



                        This stands the same for your original API call, you can:



                        function foo() {
                        // RETURN the promise
                        return fetch("/echo/json").then(function(response){
                        return response.json(); // process it inside the `then`
                        });
                        }

                        foo().then(function(response){
                        // access the value inside the `then`
                        })


                        So this works just as well. We've learned we can't return values from already asynchronous calls but we can use promises and chain them to perform processing. We now know how to return the response from an asynchronous call.



                        ES2015 (ES6)



                        ES6 introduces generators which are functions that can return in the middle and then resume the point they were at. This is typically useful for sequences, for example:



                        function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
                        yield 1;
                        yield 2;
                        while(true) yield 3;
                        }


                        Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility there is one particular interesting case.



                        If the sequence we're producing is a sequence of actions rather than numbers - we can pause the function whenever an action is yielded and wait for it before we resume the function. So instead of a sequence of numbers, we need a sequence of future values - that is: promises.



                        This somewhat tricky but very powerful trick lets us write asynchronous code in a synchronous manner. There are several "runners" that do this for you, writing one is a short few lines of code but is beyond the scope of this answer. I'll be using Bluebird's Promise.coroutine here, but there are other wrappers like co or Q.async.



                        var foo = coroutine(function*(){
                        var data = yield fetch("/echo/json"); // notice the yield
                        // code here only executes _after_ the request is done
                        return data.json(); // data is defined
                        });


                        This method returns a promise itself, which we can consume from other coroutines. For example:



                        var main = coroutine(function*(){
                        var bar = yield foo(); // wait our earlier coroutine, it returns a promise
                        // server call done here, code below executes when done
                        var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
                        console.log(baz); // runs after both requests done
                        });
                        main();


                        ES2016 (ES7)



                        In ES7, this is further standardized, there are several proposals right now but in all of them you can await promise. This is just "sugar" (nicer syntax) for the ES6 proposal above by adding the async and await keywords. Making the above example:



                        async function foo(){
                        var data = await fetch("/echo/json"); // notice the await
                        // code here only executes _after_ the request is done
                        return data.json(); // data is defined
                        }


                        It still returns a promise just the same :)






                        share|improve this answer














                        If you're using promises, this answer is for you.



                        This means AngularJS, jQuery (with deferred), native XHR's replacement (fetch), EmberJS, BackboneJS's save or any node library that returns promises.



                        Your code should be something along the lines of this:



                        function foo() {
                        var data;
                        // or $.get(...).then, or request(...).then, or query(...).then
                        fetch("/echo/json").then(function(response){
                        data = response.json();
                        });
                        return data;
                        }

                        var result = foo(); // result is always undefined no matter what.


                        Felix Kling did a fine job writing an answer for people using jQuery with callbacks for AJAX. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.





                        The core issue



                        The JavaScript concurrency model in the browser and on the server with NodeJS/io.js is asynchronous and reactive.



                        Whenever you call a method that returns a promise, the then handlers are always executed asynchronously - that is, after the code below them that is not in a .then handler.



                        This means when you're returning data the then handler you've defined did not execute yet. This in turn means that the value you're returning has not been set to the correct value in time.



                        Here is a simple analogy for the issue:




                            function getFive(){
                        var data;
                        setTimeout(function(){ // set a timer for one second in the future
                        data = 5; // after a second, do this
                        }, 1000);
                        return data;
                        }
                        document.body.innerHTML = getFive(); // `undefined` here and not 5





                        The value of data is undefined since the data = 5 part has not executed yet. It will likely execute in a second but by that time it is irrelevant to the returned value.



                        Since the operation did not happen yet (AJAX, server call, IO, timer) you're returning the value before the request got the chance to tell your code what that value is.



                        One possible solution to this problem is to code re-actively , telling your program what to do when the calculation completed. Promises actively enable this by being temporal (time-sensitive) in nature.



                        Quick recap on promises



                        A Promise is a value over time. Promises have state, they start as pending with no value and can settle to:





                        • fulfilled meaning that the computation completed successfully.


                        • rejected meaning that the computation failed.


                        A promise can only change states once after which it will always stay at the same state forever. You can attach then handlers to promises to extract their value and handle errors. then handlers allow chaining of calls. Promises are created by using APIs that return them. For example, the more modern AJAX replacement fetch or jQuery's $.get return promises.



                        When we call .then on a promise and return something from it - we get a promise for the processed value. If we return another promise we'll get amazing things, but let's hold our horses.



                        With promises



                        Let's see how we can solve the above issue with promises. First, let's demonstrate our understanding of promise states from above by using the Promise constructor for creating a delay function:



                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }


                        Now, after we converted setTimeout to use promises, we can use then to make it count:






                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }

                        function getFive(){
                        // we're RETURNING the promise, remember, a promise is a wrapper over our value
                        return delay(100).then(function(){ // when the promise is ready
                        return 5; // return the value 5, promises are all about return values
                        })
                        }
                        // we _have_ to wrap it like this in the call site, we can't access the plain value
                        getFive().then(function(five){
                        document.body.innerHTML = five;
                        });





                        Basically, instead of returning a value which we can't do because of the concurrency model - we're returning a wrapper for a value that we can unwrap with then. It's like a box you can open with then.



                        Applying this



                        This stands the same for your original API call, you can:



                        function foo() {
                        // RETURN the promise
                        return fetch("/echo/json").then(function(response){
                        return response.json(); // process it inside the `then`
                        });
                        }

                        foo().then(function(response){
                        // access the value inside the `then`
                        })


                        So this works just as well. We've learned we can't return values from already asynchronous calls but we can use promises and chain them to perform processing. We now know how to return the response from an asynchronous call.



                        ES2015 (ES6)



                        ES6 introduces generators which are functions that can return in the middle and then resume the point they were at. This is typically useful for sequences, for example:



                        function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
                        yield 1;
                        yield 2;
                        while(true) yield 3;
                        }


                        Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility there is one particular interesting case.



                        If the sequence we're producing is a sequence of actions rather than numbers - we can pause the function whenever an action is yielded and wait for it before we resume the function. So instead of a sequence of numbers, we need a sequence of future values - that is: promises.



                        This somewhat tricky but very powerful trick lets us write asynchronous code in a synchronous manner. There are several "runners" that do this for you, writing one is a short few lines of code but is beyond the scope of this answer. I'll be using Bluebird's Promise.coroutine here, but there are other wrappers like co or Q.async.



                        var foo = coroutine(function*(){
                        var data = yield fetch("/echo/json"); // notice the yield
                        // code here only executes _after_ the request is done
                        return data.json(); // data is defined
                        });


                        This method returns a promise itself, which we can consume from other coroutines. For example:



                        var main = coroutine(function*(){
                        var bar = yield foo(); // wait our earlier coroutine, it returns a promise
                        // server call done here, code below executes when done
                        var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
                        console.log(baz); // runs after both requests done
                        });
                        main();


                        ES2016 (ES7)



                        In ES7, this is further standardized, there are several proposals right now but in all of them you can await promise. This is just "sugar" (nicer syntax) for the ES6 proposal above by adding the async and await keywords. Making the above example:



                        async function foo(){
                        var data = await fetch("/echo/json"); // notice the await
                        // code here only executes _after_ the request is done
                        return data.json(); // data is defined
                        }


                        It still returns a promise just the same :)






                            function getFive(){
                        var data;
                        setTimeout(function(){ // set a timer for one second in the future
                        data = 5; // after a second, do this
                        }, 1000);
                        return data;
                        }
                        document.body.innerHTML = getFive(); // `undefined` here and not 5





                            function getFive(){
                        var data;
                        setTimeout(function(){ // set a timer for one second in the future
                        data = 5; // after a second, do this
                        }, 1000);
                        return data;
                        }
                        document.body.innerHTML = getFive(); // `undefined` here and not 5





                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }

                        function getFive(){
                        // we're RETURNING the promise, remember, a promise is a wrapper over our value
                        return delay(100).then(function(){ // when the promise is ready
                        return 5; // return the value 5, promises are all about return values
                        })
                        }
                        // we _have_ to wrap it like this in the call site, we can't access the plain value
                        getFive().then(function(five){
                        document.body.innerHTML = five;
                        });





                        function delay(ms){ // takes amount of milliseconds
                        // returns a new promise
                        return new Promise(function(resolve, reject){
                        setTimeout(function(){ // when the time is up
                        resolve(); // change the promise to the fulfilled state
                        }, ms);
                        });
                        }

                        function getFive(){
                        // we're RETURNING the promise, remember, a promise is a wrapper over our value
                        return delay(100).then(function(){ // when the promise is ready
                        return 5; // return the value 5, promises are all about return values
                        })
                        }
                        // we _have_ to wrap it like this in the call site, we can't access the plain value
                        getFive().then(function(five){
                        document.body.innerHTML = five;
                        });






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited May 23 '17 at 12:34









                        Community

                        11




                        11










                        answered May 12 '15 at 2:22









                        Benjamin Gruenbaum

                        185k63398434




                        185k63398434








                        • 17




                          ES 2016 looks like the final solution to this problem once and for all.
                          – ShrekOverflow
                          May 12 '15 at 16:42






                        • 10




                          The absolutely final solution, for once and for all? What about the totally absolutely final solution, for once and for all plus one?
                          – Shmiddty
                          May 13 '15 at 6:11






                        • 3




                          @recurf first of all "where the hell" is hardly appropriate for this site (kids are using it too, for one). Second of all - it's a function parameter, I could have named it anywhere else and it would work just as fine.
                          – Benjamin Gruenbaum
                          Jan 20 '17 at 0:08










                        • @TDR by awaiting with async/await or with a then
                          – Benjamin Gruenbaum
                          Jul 17 at 18:45














                        • 17




                          ES 2016 looks like the final solution to this problem once and for all.
                          – ShrekOverflow
                          May 12 '15 at 16:42






                        • 10




                          The absolutely final solution, for once and for all? What about the totally absolutely final solution, for once and for all plus one?
                          – Shmiddty
                          May 13 '15 at 6:11






                        • 3




                          @recurf first of all "where the hell" is hardly appropriate for this site (kids are using it too, for one). Second of all - it's a function parameter, I could have named it anywhere else and it would work just as fine.
                          – Benjamin Gruenbaum
                          Jan 20 '17 at 0:08










                        • @TDR by awaiting with async/await or with a then
                          – Benjamin Gruenbaum
                          Jul 17 at 18:45








                        17




                        17




                        ES 2016 looks like the final solution to this problem once and for all.
                        – ShrekOverflow
                        May 12 '15 at 16:42




                        ES 2016 looks like the final solution to this problem once and for all.
                        – ShrekOverflow
                        May 12 '15 at 16:42




                        10




                        10




                        The absolutely final solution, for once and for all? What about the totally absolutely final solution, for once and for all plus one?
                        – Shmiddty
                        May 13 '15 at 6:11




                        The absolutely final solution, for once and for all? What about the totally absolutely final solution, for once and for all plus one?
                        – Shmiddty
                        May 13 '15 at 6:11




                        3




                        3




                        @recurf first of all "where the hell" is hardly appropriate for this site (kids are using it too, for one). Second of all - it's a function parameter, I could have named it anywhere else and it would work just as fine.
                        – Benjamin Gruenbaum
                        Jan 20 '17 at 0:08




                        @recurf first of all "where the hell" is hardly appropriate for this site (kids are using it too, for one). Second of all - it's a function parameter, I could have named it anywhere else and it would work just as fine.
                        – Benjamin Gruenbaum
                        Jan 20 '17 at 0:08












                        @TDR by awaiting with async/await or with a then
                        – Benjamin Gruenbaum
                        Jul 17 at 18:45




                        @TDR by awaiting with async/await or with a then
                        – Benjamin Gruenbaum
                        Jul 17 at 18:45










                        up vote
                        206
                        down vote













                        You are using Ajax incorrectly. The idea is not to have it return anything, but instead hand off the data to something called a callback function, which handles the data.



                        That is:



                        function handleData( responseData ) {

                        // Do what you want with the data
                        console.log(responseData);
                        }

                        $.ajax({
                        url: "hi.php",
                        ...
                        success: function ( data, status, XHR ) {
                        handleData(data);
                        }
                        });


                        Returning anything in the submit handler will not do anything. You must instead either hand off the data, or do what you want with it directly inside the success function.






                        share|improve this answer



















                        • 9




                          This answer is completely semantic... your success method is just a callback within a callback. You could just have success: handleData and it would work.
                          – Jacques
                          Jan 4 '16 at 15:49






                        • 3




                          And what if you want to return the "responseData" outside of "handleData" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "handleData" ...
                          – pesho hristov
                          Feb 19 '16 at 16:02










                        • @Jacques & @pesho hristov You missed this point. Submit handler is not the success method, it's the surrounding scope of $.ajax.
                          – travnik
                          May 28 at 12:37










                        • @travnik I didn't miss that. If you took the contents of handleData and put it in the success method it would act exactly the same...
                          – Jacques
                          Jun 13 at 1:21















                        up vote
                        206
                        down vote













                        You are using Ajax incorrectly. The idea is not to have it return anything, but instead hand off the data to something called a callback function, which handles the data.



                        That is:



                        function handleData( responseData ) {

                        // Do what you want with the data
                        console.log(responseData);
                        }

                        $.ajax({
                        url: "hi.php",
                        ...
                        success: function ( data, status, XHR ) {
                        handleData(data);
                        }
                        });


                        Returning anything in the submit handler will not do anything. You must instead either hand off the data, or do what you want with it directly inside the success function.






                        share|improve this answer



















                        • 9




                          This answer is completely semantic... your success method is just a callback within a callback. You could just have success: handleData and it would work.
                          – Jacques
                          Jan 4 '16 at 15:49






                        • 3




                          And what if you want to return the "responseData" outside of "handleData" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "handleData" ...
                          – pesho hristov
                          Feb 19 '16 at 16:02










                        • @Jacques & @pesho hristov You missed this point. Submit handler is not the success method, it's the surrounding scope of $.ajax.
                          – travnik
                          May 28 at 12:37










                        • @travnik I didn't miss that. If you took the contents of handleData and put it in the success method it would act exactly the same...
                          – Jacques
                          Jun 13 at 1:21













                        up vote
                        206
                        down vote










                        up vote
                        206
                        down vote









                        You are using Ajax incorrectly. The idea is not to have it return anything, but instead hand off the data to something called a callback function, which handles the data.



                        That is:



                        function handleData( responseData ) {

                        // Do what you want with the data
                        console.log(responseData);
                        }

                        $.ajax({
                        url: "hi.php",
                        ...
                        success: function ( data, status, XHR ) {
                        handleData(data);
                        }
                        });


                        Returning anything in the submit handler will not do anything. You must instead either hand off the data, or do what you want with it directly inside the success function.






                        share|improve this answer














                        You are using Ajax incorrectly. The idea is not to have it return anything, but instead hand off the data to something called a callback function, which handles the data.



                        That is:



                        function handleData( responseData ) {

                        // Do what you want with the data
                        console.log(responseData);
                        }

                        $.ajax({
                        url: "hi.php",
                        ...
                        success: function ( data, status, XHR ) {
                        handleData(data);
                        }
                        });


                        Returning anything in the submit handler will not do anything. You must instead either hand off the data, or do what you want with it directly inside the success function.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Nov 21 '15 at 14:07









                        Peter Mortensen

                        13.4k1983111




                        13.4k1983111










                        answered May 23 '14 at 2:05









                        Nic

                        1,9781812




                        1,9781812








                        • 9




                          This answer is completely semantic... your success method is just a callback within a callback. You could just have success: handleData and it would work.
                          – Jacques
                          Jan 4 '16 at 15:49






                        • 3




                          And what if you want to return the "responseData" outside of "handleData" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "handleData" ...
                          – pesho hristov
                          Feb 19 '16 at 16:02










                        • @Jacques & @pesho hristov You missed this point. Submit handler is not the success method, it's the surrounding scope of $.ajax.
                          – travnik
                          May 28 at 12:37










                        • @travnik I didn't miss that. If you took the contents of handleData and put it in the success method it would act exactly the same...
                          – Jacques
                          Jun 13 at 1:21














                        • 9




                          This answer is completely semantic... your success method is just a callback within a callback. You could just have success: handleData and it would work.
                          – Jacques
                          Jan 4 '16 at 15:49






                        • 3




                          And what if you want to return the "responseData" outside of "handleData" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "handleData" ...
                          – pesho hristov
                          Feb 19 '16 at 16:02










                        • @Jacques & @pesho hristov You missed this point. Submit handler is not the success method, it's the surrounding scope of $.ajax.
                          – travnik
                          May 28 at 12:37










                        • @travnik I didn't miss that. If you took the contents of handleData and put it in the success method it would act exactly the same...
                          – Jacques
                          Jun 13 at 1:21








                        9




                        9




                        This answer is completely semantic... your success method is just a callback within a callback. You could just have success: handleData and it would work.
                        – Jacques
                        Jan 4 '16 at 15:49




                        This answer is completely semantic... your success method is just a callback within a callback. You could just have success: handleData and it would work.
                        – Jacques
                        Jan 4 '16 at 15:49




                        3




                        3




                        And what if you want to return the "responseData" outside of "handleData" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "handleData" ...
                        – pesho hristov
                        Feb 19 '16 at 16:02




                        And what if you want to return the "responseData" outside of "handleData" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "handleData" ...
                        – pesho hristov
                        Feb 19 '16 at 16:02












                        @Jacques & @pesho hristov You missed this point. Submit handler is not the success method, it's the surrounding scope of $.ajax.
                        – travnik
                        May 28 at 12:37




                        @Jacques & @pesho hristov You missed this point. Submit handler is not the success method, it's the surrounding scope of $.ajax.
                        – travnik
                        May 28 at 12:37












                        @travnik I didn't miss that. If you took the contents of handleData and put it in the success method it would act exactly the same...
                        – Jacques
                        Jun 13 at 1:21




                        @travnik I didn't miss that. If you took the contents of handleData and put it in the success method it would act exactly the same...
                        – Jacques
                        Jun 13 at 1:21










                        up vote
                        197
                        down vote













                        The simplest solution is create a JavaScript function and call it for the Ajax success callback.



                        function callServerAsync(){
                        $.ajax({
                        url: '...',
                        success: function(response) {

                        successCallback(response);
                        }
                        });
                        }

                        function successCallback(responseObj){
                        // Do something like read the response and show data
                        alert(JSON.stringify(responseObj)); // Only applicable to JSON response
                        }

                        function foo(callback) {

                        $.ajax({
                        url: '...',
                        success: function(response) {
                        return callback(null, response);
                        }
                        });
                        }

                        var result = foo(function(err, result){
                        if (!err)
                        console.log(result);
                        });





                        share|improve this answer



















                        • 2




                          I don't know who voted it negative. But this is a work around which has worked in fact i used this approach to create a whole application. The jquery.ajax don't return data so its better to use the above approach. If it's wrong then please explain and suggest better way to do it.
                          – Hemant Bavle
                          Mar 28 '14 at 18:12








                        • 11




                          Sorry, I forgot to leave a comment (I usually do!). I downvoted it. Downvotes don't indicate factual correctness or lack of, they indicate usefulness in the context or lack of. I don't find your answer useful given Felix's which already explains this only in much more detail. On a side note, why would you stringify the response if it's JSON?
                          – Benjamin Gruenbaum
                          Apr 10 '14 at 9:18






                        • 5




                          ok.. @Benjamin i used stringify, to convert a JSON Object to string. And thanks for clarifying your point. Will keep in mind to post more elaborate answers.
                          – Hemant Bavle
                          Apr 10 '14 at 10:27












                        • And what if you want to return the "responseObj" outside of "successCallback" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "successCallback" ...
                          – pesho hristov
                          Feb 19 '16 at 16:02















                        up vote
                        197
                        down vote













                        The simplest solution is create a JavaScript function and call it for the Ajax success callback.



                        function callServerAsync(){
                        $.ajax({
                        url: '...',
                        success: function(response) {

                        successCallback(response);
                        }
                        });
                        }

                        function successCallback(responseObj){
                        // Do something like read the response and show data
                        alert(JSON.stringify(responseObj)); // Only applicable to JSON response
                        }

                        function foo(callback) {

                        $.ajax({
                        url: '...',
                        success: function(response) {
                        return callback(null, response);
                        }
                        });
                        }

                        var result = foo(function(err, result){
                        if (!err)
                        console.log(result);
                        });





                        share|improve this answer



















                        • 2




                          I don't know who voted it negative. But this is a work around which has worked in fact i used this approach to create a whole application. The jquery.ajax don't return data so its better to use the above approach. If it's wrong then please explain and suggest better way to do it.
                          – Hemant Bavle
                          Mar 28 '14 at 18:12








                        • 11




                          Sorry, I forgot to leave a comment (I usually do!). I downvoted it. Downvotes don't indicate factual correctness or lack of, they indicate usefulness in the context or lack of. I don't find your answer useful given Felix's which already explains this only in much more detail. On a side note, why would you stringify the response if it's JSON?
                          – Benjamin Gruenbaum
                          Apr 10 '14 at 9:18






                        • 5




                          ok.. @Benjamin i used stringify, to convert a JSON Object to string. And thanks for clarifying your point. Will keep in mind to post more elaborate answers.
                          – Hemant Bavle
                          Apr 10 '14 at 10:27












                        • And what if you want to return the "responseObj" outside of "successCallback" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "successCallback" ...
                          – pesho hristov
                          Feb 19 '16 at 16:02













                        up vote
                        197
                        down vote










                        up vote
                        197
                        down vote









                        The simplest solution is create a JavaScript function and call it for the Ajax success callback.



                        function callServerAsync(){
                        $.ajax({
                        url: '...',
                        success: function(response) {

                        successCallback(response);
                        }
                        });
                        }

                        function successCallback(responseObj){
                        // Do something like read the response and show data
                        alert(JSON.stringify(responseObj)); // Only applicable to JSON response
                        }

                        function foo(callback) {

                        $.ajax({
                        url: '...',
                        success: function(response) {
                        return callback(null, response);
                        }
                        });
                        }

                        var result = foo(function(err, result){
                        if (!err)
                        console.log(result);
                        });





                        share|improve this answer














                        The simplest solution is create a JavaScript function and call it for the Ajax success callback.



                        function callServerAsync(){
                        $.ajax({
                        url: '...',
                        success: function(response) {

                        successCallback(response);
                        }
                        });
                        }

                        function successCallback(responseObj){
                        // Do something like read the response and show data
                        alert(JSON.stringify(responseObj)); // Only applicable to JSON response
                        }

                        function foo(callback) {

                        $.ajax({
                        url: '...',
                        success: function(response) {
                        return callback(null, response);
                        }
                        });
                        }

                        var result = foo(function(err, result){
                        if (!err)
                        console.log(result);
                        });






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Jan 15 '17 at 6:17









                        clearlight

                        8,58893858




                        8,58893858










                        answered Feb 18 '14 at 18:58









                        Hemant Bavle

                        2,36611823




                        2,36611823








                        • 2




                          I don't know who voted it negative. But this is a work around which has worked in fact i used this approach to create a whole application. The jquery.ajax don't return data so its better to use the above approach. If it's wrong then please explain and suggest better way to do it.
                          – Hemant Bavle
                          Mar 28 '14 at 18:12








                        • 11




                          Sorry, I forgot to leave a comment (I usually do!). I downvoted it. Downvotes don't indicate factual correctness or lack of, they indicate usefulness in the context or lack of. I don't find your answer useful given Felix's which already explains this only in much more detail. On a side note, why would you stringify the response if it's JSON?
                          – Benjamin Gruenbaum
                          Apr 10 '14 at 9:18






                        • 5




                          ok.. @Benjamin i used stringify, to convert a JSON Object to string. And thanks for clarifying your point. Will keep in mind to post more elaborate answers.
                          – Hemant Bavle
                          Apr 10 '14 at 10:27












                        • And what if you want to return the "responseObj" outside of "successCallback" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "successCallback" ...
                          – pesho hristov
                          Feb 19 '16 at 16:02














                        • 2




                          I don't know who voted it negative. But this is a work around which has worked in fact i used this approach to create a whole application. The jquery.ajax don't return data so its better to use the above approach. If it's wrong then please explain and suggest better way to do it.
                          – Hemant Bavle
                          Mar 28 '14 at 18:12








                        • 11




                          Sorry, I forgot to leave a comment (I usually do!). I downvoted it. Downvotes don't indicate factual correctness or lack of, they indicate usefulness in the context or lack of. I don't find your answer useful given Felix's which already explains this only in much more detail. On a side note, why would you stringify the response if it's JSON?
                          – Benjamin Gruenbaum
                          Apr 10 '14 at 9:18






                        • 5




                          ok.. @Benjamin i used stringify, to convert a JSON Object to string. And thanks for clarifying your point. Will keep in mind to post more elaborate answers.
                          – Hemant Bavle
                          Apr 10 '14 at 10:27












                        • And what if you want to return the "responseObj" outside of "successCallback" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "successCallback" ...
                          – pesho hristov
                          Feb 19 '16 at 16:02








                        2




                        2




                        I don't know who voted it negative. But this is a work around which has worked in fact i used this approach to create a whole application. The jquery.ajax don't return data so its better to use the above approach. If it's wrong then please explain and suggest better way to do it.
                        – Hemant Bavle
                        Mar 28 '14 at 18:12






                        I don't know who voted it negative. But this is a work around which has worked in fact i used this approach to create a whole application. The jquery.ajax don't return data so its better to use the above approach. If it's wrong then please explain and suggest better way to do it.
                        – Hemant Bavle
                        Mar 28 '14 at 18:12






                        11




                        11




                        Sorry, I forgot to leave a comment (I usually do!). I downvoted it. Downvotes don't indicate factual correctness or lack of, they indicate usefulness in the context or lack of. I don't find your answer useful given Felix's which already explains this only in much more detail. On a side note, why would you stringify the response if it's JSON?
                        – Benjamin Gruenbaum
                        Apr 10 '14 at 9:18




                        Sorry, I forgot to leave a comment (I usually do!). I downvoted it. Downvotes don't indicate factual correctness or lack of, they indicate usefulness in the context or lack of. I don't find your answer useful given Felix's which already explains this only in much more detail. On a side note, why would you stringify the response if it's JSON?
                        – Benjamin Gruenbaum
                        Apr 10 '14 at 9:18




                        5




                        5




                        ok.. @Benjamin i used stringify, to convert a JSON Object to string. And thanks for clarifying your point. Will keep in mind to post more elaborate answers.
                        – Hemant Bavle
                        Apr 10 '14 at 10:27






                        ok.. @Benjamin i used stringify, to convert a JSON Object to string. And thanks for clarifying your point. Will keep in mind to post more elaborate answers.
                        – Hemant Bavle
                        Apr 10 '14 at 10:27














                        And what if you want to return the "responseObj" outside of "successCallback" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "successCallback" ...
                        – pesho hristov
                        Feb 19 '16 at 16:02




                        And what if you want to return the "responseObj" outside of "successCallback" ... :) ... how will you do it ... ? ... cause a simple return will return it to the "success" callback of the ajax ... and not outside of "successCallback" ...
                        – pesho hristov
                        Feb 19 '16 at 16:02










                        up vote
                        165
                        down vote













                        I will answer with a horrible-looking, hand-drawn comic. The second image is the reason why result is undefined in your code example.



                        enter image description here






                        share|improve this answer



















                        • 22




                          A picture is worth a thousand words, Person A - Ask's person B details to fix his car, in turn Person B - Makes Ajax Call and waits for response from server for car fixing details, when response is received, Ajax Success function calls the Person B function and passes the response as argument to it, Person A receives the answer.
                          – stom
                          Oct 31 '16 at 17:48








                        • 4




                          Would be great if you added lines of code with each image to illustrate the concepts.
                          – Hassan Baig
                          Feb 5 at 0:32






                        • 5




                          The best explanation I've ever come across
                          – anonymous
                          Mar 31 at 15:52






                        • 1




                          Best Explanation
                          – Vijay S
                          Aug 23 at 9:42















                        up vote
                        165
                        down vote













                        I will answer with a horrible-looking, hand-drawn comic. The second image is the reason why result is undefined in your code example.



                        enter image description here






                        share|improve this answer



















                        • 22




                          A picture is worth a thousand words, Person A - Ask's person B details to fix his car, in turn Person B - Makes Ajax Call and waits for response from server for car fixing details, when response is received, Ajax Success function calls the Person B function and passes the response as argument to it, Person A receives the answer.
                          – stom
                          Oct 31 '16 at 17:48








                        • 4




                          Would be great if you added lines of code with each image to illustrate the concepts.
                          – Hassan Baig
                          Feb 5 at 0:32






                        • 5




                          The best explanation I've ever come across
                          – anonymous
                          Mar 31 at 15:52






                        • 1




                          Best Explanation
                          – Vijay S
                          Aug 23 at 9:42













                        up vote
                        165
                        down vote










                        up vote
                        165
                        down vote









                        I will answer with a horrible-looking, hand-drawn comic. The second image is the reason why result is undefined in your code example.



                        enter image description here






                        share|improve this answer














                        I will answer with a horrible-looking, hand-drawn comic. The second image is the reason why result is undefined in your code example.



                        enter image description here







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Aug 11 '16 at 17:12

























                        answered Aug 11 '16 at 14:17









                        Johannes Fahrenkrug

                        30.9k1595140




                        30.9k1595140








                        • 22




                          A picture is worth a thousand words, Person A - Ask's person B details to fix his car, in turn Person B - Makes Ajax Call and waits for response from server for car fixing details, when response is received, Ajax Success function calls the Person B function and passes the response as argument to it, Person A receives the answer.
                          – stom
                          Oct 31 '16 at 17:48








                        • 4




                          Would be great if you added lines of code with each image to illustrate the concepts.
                          – Hassan Baig
                          Feb 5 at 0:32






                        • 5




                          The best explanation I've ever come across
                          – anonymous
                          Mar 31 at 15:52






                        • 1




                          Best Explanation
                          – Vijay S
                          Aug 23 at 9:42














                        • 22




                          A picture is worth a thousand words, Person A - Ask's person B details to fix his car, in turn Person B - Makes Ajax Call and waits for response from server for car fixing details, when response is received, Ajax Success function calls the Person B function and passes the response as argument to it, Person A receives the answer.
                          – stom
                          Oct 31 '16 at 17:48








                        • 4




                          Would be great if you added lines of code with each image to illustrate the concepts.
                          – Hassan Baig
                          Feb 5 at 0:32






                        • 5




                          The best explanation I've ever come across
                          – anonymous
                          Mar 31 at 15:52






                        • 1




                          Best Explanation
                          – Vijay S
                          Aug 23 at 9:42








                        22




                        22




                        A picture is worth a thousand words, Person A - Ask's person B details to fix his car, in turn Person B - Makes Ajax Call and waits for response from server for car fixing details, when response is received, Ajax Success function calls the Person B function and passes the response as argument to it, Person A receives the answer.
                        – stom
                        Oct 31 '16 at 17:48






                        A picture is worth a thousand words, Person A - Ask's person B details to fix his car, in turn Person B - Makes Ajax Call and waits for response from server for car fixing details, when response is received, Ajax Success function calls the Person B function and passes the response as argument to it, Person A receives the answer.
                        – stom
                        Oct 31 '16 at 17:48






                        4




                        4




                        Would be great if you added lines of code with each image to illustrate the concepts.
                        – Hassan Baig
                        Feb 5 at 0:32




                        Would be great if you added lines of code with each image to illustrate the concepts.
                        – Hassan Baig
                        Feb 5 at 0:32




                        5




                        5




                        The best explanation I've ever come across
                        – anonymous
                        Mar 31 at 15:52




                        The best explanation I've ever come across
                        – anonymous
                        Mar 31 at 15:52




                        1




                        1




                        Best Explanation
                        – Vijay S
                        Aug 23 at 9:42




                        Best Explanation
                        – Vijay S
                        Aug 23 at 9:42










                        up vote
                        123
                        down vote













                        Angular1



                        For people who are using AngularJS, can handle this situation using Promises.



                        Here it says,




                        Promises can be used to unnest asynchronous functions and allows one to chain multiple functions together.




                        You can find a nice explanation here also.



                        Example found in docs mentioned below.



                          promiseB = promiseA.then(
                        function onSuccess(result) {
                        return result + 1;
                        }
                        ,function onError(err) {
                        //Handle error
                        }
                        );

                        // promiseB will be resolved immediately after promiseA is resolved
                        // and its value will be the result of promiseA incremented by 1.


                        Angular2 and Later



                        In Angular2 with look at the following example, but its recommended to use Observables with Angular2.



                         search(term: string) {
                        return this.http
                        .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
                        .map((response) => response.json())
                        .toPromise();


                        }



                        You can consume that in this way,



                        search() {
                        this.searchService.search(this.searchField.value)
                        .then((result) => {
                        this.result = result.artists.items;
                        })
                        .catch((error) => console.error(error));
                        }


                        See the original post here. But Typescript does not support native es6 Promises, if you want to use it, you might need plugin for that.



                        Additionally here is the promises spec define here.






                        share|improve this answer



















                        • 13




                          This does not explain how promises would solve this issue at all though.
                          – Benjamin Gruenbaum
                          Nov 4 '14 at 2:29






                        • 4




                          It doesn't work. promiseB will get 'undefined'
                          – An Overflowed Stack
                          Nov 21 '14 at 15:35






                        • 3




                          jQuery and fetch methods both return promises as well. I would suggest revising your answer. Though jQuery's isn't quite the same (then is there, but catch isn't).
                          – Tracker1
                          Feb 19 '15 at 19:24















                        up vote
                        123
                        down vote













                        Angular1



                        For people who are using AngularJS, can handle this situation using Promises.



                        Here it says,




                        Promises can be used to unnest asynchronous functions and allows one to chain multiple functions together.




                        You can find a nice explanation here also.



                        Example found in docs mentioned below.



                          promiseB = promiseA.then(
                        function onSuccess(result) {
                        return result + 1;
                        }
                        ,function onError(err) {
                        //Handle error
                        }
                        );

                        // promiseB will be resolved immediately after promiseA is resolved
                        // and its value will be the result of promiseA incremented by 1.


                        Angular2 and Later



                        In Angular2 with look at the following example, but its recommended to use Observables with Angular2.



                         search(term: string) {
                        return this.http
                        .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
                        .map((response) => response.json())
                        .toPromise();


                        }



                        You can consume that in this way,



                        search() {
                        this.searchService.search(this.searchField.value)
                        .then((result) => {
                        this.result = result.artists.items;
                        })
                        .catch((error) => console.error(error));
                        }


                        See the original post here. But Typescript does not support native es6 Promises, if you want to use it, you might need plugin for that.



                        Additionally here is the promises spec define here.






                        share|improve this answer



















                        • 13




                          This does not explain how promises would solve this issue at all though.
                          – Benjamin Gruenbaum
                          Nov 4 '14 at 2:29






                        • 4




                          It doesn't work. promiseB will get 'undefined'
                          – An Overflowed Stack
                          Nov 21 '14 at 15:35






                        • 3




                          jQuery and fetch methods both return promises as well. I would suggest revising your answer. Though jQuery's isn't quite the same (then is there, but catch isn't).
                          – Tracker1
                          Feb 19 '15 at 19:24













                        up vote
                        123
                        down vote










                        up vote
                        123
                        down vote









                        Angular1



                        For people who are using AngularJS, can handle this situation using Promises.



                        Here it says,




                        Promises can be used to unnest asynchronous functions and allows one to chain multiple functions together.




                        You can find a nice explanation here also.



                        Example found in docs mentioned below.



                          promiseB = promiseA.then(
                        function onSuccess(result) {
                        return result + 1;
                        }
                        ,function onError(err) {
                        //Handle error
                        }
                        );

                        // promiseB will be resolved immediately after promiseA is resolved
                        // and its value will be the result of promiseA incremented by 1.


                        Angular2 and Later



                        In Angular2 with look at the following example, but its recommended to use Observables with Angular2.



                         search(term: string) {
                        return this.http
                        .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
                        .map((response) => response.json())
                        .toPromise();


                        }



                        You can consume that in this way,



                        search() {
                        this.searchService.search(this.searchField.value)
                        .then((result) => {
                        this.result = result.artists.items;
                        })
                        .catch((error) => console.error(error));
                        }


                        See the original post here. But Typescript does not support native es6 Promises, if you want to use it, you might need plugin for that.



                        Additionally here is the promises spec define here.






                        share|improve this answer














                        Angular1



                        For people who are using AngularJS, can handle this situation using Promises.



                        Here it says,




                        Promises can be used to unnest asynchronous functions and allows one to chain multiple functions together.




                        You can find a nice explanation here also.



                        Example found in docs mentioned below.



                          promiseB = promiseA.then(
                        function onSuccess(result) {
                        return result + 1;
                        }
                        ,function onError(err) {
                        //Handle error
                        }
                        );

                        // promiseB will be resolved immediately after promiseA is resolved
                        // and its value will be the result of promiseA incremented by 1.


                        Angular2 and Later



                        In Angular2 with look at the following example, but its recommended to use Observables with Angular2.



                         search(term: string) {
                        return this.http
                        .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
                        .map((response) => response.json())
                        .toPromise();


                        }



                        You can consume that in this way,



                        search() {
                        this.searchService.search(this.searchField.value)
                        .then((result) => {
                        this.result = result.artists.items;
                        })
                        .catch((error) => console.error(error));
                        }


                        See the original post here. But Typescript does not support native es6 Promises, if you want to use it, you might need plugin for that.



                        Additionally here is the promises spec define here.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Jul 6 '17 at 4:45

























                        answered Aug 26 '14 at 8:11









                        Maleen Abewardana

                        6,25332733




                        6,25332733








                        • 13




                          This does not explain how promises would solve this issue at all though.
                          – Benjamin Gruenbaum
                          Nov 4 '14 at 2:29






                        • 4




                          It doesn't work. promiseB will get 'undefined'
                          – An Overflowed Stack
                          Nov 21 '14 at 15:35






                        • 3




                          jQuery and fetch methods both return promises as well. I would suggest revising your answer. Though jQuery's isn't quite the same (then is there, but catch isn't).
                          – Tracker1
                          Feb 19 '15 at 19:24














                        • 13




                          This does not explain how promises would solve this issue at all though.
                          – Benjamin Gruenbaum
                          Nov 4 '14 at 2:29






                        • 4




                          It doesn't work. promiseB will get 'undefined'
                          – An Overflowed Stack
                          Nov 21 '14 at 15:35






                        • 3




                          jQuery and fetch methods both return promises as well. I would suggest revising your answer. Though jQuery's isn't quite the same (then is there, but catch isn't).
                          – Tracker1
                          Feb 19 '15 at 19:24








                        13




                        13




                        This does not explain how promises would solve this issue at all though.
                        – Benjamin Gruenbaum
                        Nov 4 '14 at 2:29




                        This does not explain how promises would solve this issue at all though.
                        – Benjamin Gruenbaum
                        Nov 4 '14 at 2:29




                        4




                        4




                        It doesn't work. promiseB will get 'undefined'
                        – An Overflowed Stack
                        Nov 21 '14 at 15:35




                        It doesn't work. promiseB will get 'undefined'
                        – An Overflowed Stack
                        Nov 21 '14 at 15:35




                        3




                        3




                        jQuery and fetch methods both return promises as well. I would suggest revising your answer. Though jQuery's isn't quite the same (then is there, but catch isn't).
                        – Tracker1
                        Feb 19 '15 at 19:24




                        jQuery and fetch methods both return promises as well. I would suggest revising your answer. Though jQuery's isn't quite the same (then is there, but catch isn't).
                        – Tracker1
                        Feb 19 '15 at 19:24










                        up vote
                        101
                        down vote













                        Most of the answers here give useful suggestions for when you have a single async operation, but sometimes, this comes up when you need to do an asynchronous operation for each entry in an array or other list-like structure. The temptation is to do this:



                        // WRONG
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log(results); // E.g., using them, returning them, etc.


                        Example:






                        // WRONG
                        var theArray = [1, 2, 3];
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log("Results:", results); // E.g., using them, returning them, etc.

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        The reason that doesn't work is that the callbacks from doSomethingAsync haven't run yet by the time you're trying to use the results.



                        So, if you have an array (or list of some kind) and want to do async operations for each entry, you have two options: Do the operations in parallel (overlapping), or in series (one after another in sequence).



                        Parallel



                        You can start all of them and keep track of how many callbacks you're expecting, and then use the results when you've gotten that many callbacks:



                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });


                        Example:






                        var theArray = [1, 2, 3];
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (We could do away with expecting and just use results.length === theArray.length, but that leaves us open to the possibility that theArray is changed while the calls are outstanding...)



                        Notice how we use the index from forEach to save the result in results in the same position as the entry it relates to, even if the results arrive out of order (since async calls don't necessarily complete in the order in which they were started).



                        But what if you need to return those results from a function? As the other answers have pointed out, you can't; you have to have your function accept and call a callback (or return a Promise). Here's a callback version:



                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith(theArray, function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        Or here's a version returning a Promise instead:



                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Of course, if doSomethingAsync passed us errors, we'd use reject to reject the promise when we got an error.)



                        Example:






                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (Or alternately, you could make a wrapper for doSomethingAsync that returns a promise, and then do the below...)



                        If doSomethingAsync gives you a Promise, you can use Promise.all:



                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        Note that Promise.all resolves its promise with an array of the results of all of the promises you give it when they are all resolved, or rejects its promise when the first of the promises you give it rejects.



                        Series



                        Suppose you don't want the operations to be in parallel? If you want to run them one after another, you need to wait for each operation to complete before you start the next. Here's an example of a function that does that and calls a callback with the result:



                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith(theArray, function(results) {
                        console.log("Results:", results);
                        });


                        (Since we're doing the work in series, we can just use results.push(result) since we know we won't get results out of order. In the above we could have used results[index] = result;, but in some of the following examples we don't have an index to use.)



                        Example:






                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (Or, again, build a wrapper for doSomethingAsync that gives you a promise and do the below...)



                        If doSomethingAsync gives you a Promise, if you can use ES2017+ syntax (perhaps with a transpiler like Babel), you can use an async function with for-of and await:



                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith(theArray).then(results => {
                        console.log("Results:", results);
                        });


                        Example:






                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        If you can't use ES2017+ syntax (yet), you can use a variation on the "Promise reduce" pattern (this is more complex than the usual Promise reduce because we're not passing the result from one into the next, but instead gathering up their results in an array):



                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        ...which is less cumbersome with ES2015+ arrow functions:



                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith(theArray).then(results => {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }








                        share|improve this answer



















                        • 1




                          Could you explain how the if (--expecting === 0) part of the code works please? The callback version of your solution is working great for me, I just don't understand how, with that statement, you are checking the number of responses completed. Appreciate it's just lack of knowledge on my part. Is there an alternative way that check could be written?
                          – Sarah
                          May 28 '17 at 10:21












                        • @Sarah: expecting starts out with the value of array.length, which is how many requests we're going to make. We know the callback won't be called until all of those requests are started. In the callback, if (--expecting === 0) does this: 1. Decrements expecting (we've received a response, so we're expecting one fewer response) and if the value after the decrement is 0 (we're not expecting any more responses), we're done!
                          – T.J. Crowder
                          May 28 '17 at 18:31















                        up vote
                        101
                        down vote













                        Most of the answers here give useful suggestions for when you have a single async operation, but sometimes, this comes up when you need to do an asynchronous operation for each entry in an array or other list-like structure. The temptation is to do this:



                        // WRONG
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log(results); // E.g., using them, returning them, etc.


                        Example:






                        // WRONG
                        var theArray = [1, 2, 3];
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log("Results:", results); // E.g., using them, returning them, etc.

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        The reason that doesn't work is that the callbacks from doSomethingAsync haven't run yet by the time you're trying to use the results.



                        So, if you have an array (or list of some kind) and want to do async operations for each entry, you have two options: Do the operations in parallel (overlapping), or in series (one after another in sequence).



                        Parallel



                        You can start all of them and keep track of how many callbacks you're expecting, and then use the results when you've gotten that many callbacks:



                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });


                        Example:






                        var theArray = [1, 2, 3];
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (We could do away with expecting and just use results.length === theArray.length, but that leaves us open to the possibility that theArray is changed while the calls are outstanding...)



                        Notice how we use the index from forEach to save the result in results in the same position as the entry it relates to, even if the results arrive out of order (since async calls don't necessarily complete in the order in which they were started).



                        But what if you need to return those results from a function? As the other answers have pointed out, you can't; you have to have your function accept and call a callback (or return a Promise). Here's a callback version:



                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith(theArray, function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        Or here's a version returning a Promise instead:



                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Of course, if doSomethingAsync passed us errors, we'd use reject to reject the promise when we got an error.)



                        Example:






                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (Or alternately, you could make a wrapper for doSomethingAsync that returns a promise, and then do the below...)



                        If doSomethingAsync gives you a Promise, you can use Promise.all:



                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        Note that Promise.all resolves its promise with an array of the results of all of the promises you give it when they are all resolved, or rejects its promise when the first of the promises you give it rejects.



                        Series



                        Suppose you don't want the operations to be in parallel? If you want to run them one after another, you need to wait for each operation to complete before you start the next. Here's an example of a function that does that and calls a callback with the result:



                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith(theArray, function(results) {
                        console.log("Results:", results);
                        });


                        (Since we're doing the work in series, we can just use results.push(result) since we know we won't get results out of order. In the above we could have used results[index] = result;, but in some of the following examples we don't have an index to use.)



                        Example:






                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (Or, again, build a wrapper for doSomethingAsync that gives you a promise and do the below...)



                        If doSomethingAsync gives you a Promise, if you can use ES2017+ syntax (perhaps with a transpiler like Babel), you can use an async function with for-of and await:



                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith(theArray).then(results => {
                        console.log("Results:", results);
                        });


                        Example:






                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        If you can't use ES2017+ syntax (yet), you can use a variation on the "Promise reduce" pattern (this is more complex than the usual Promise reduce because we're not passing the result from one into the next, but instead gathering up their results in an array):



                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        ...which is less cumbersome with ES2015+ arrow functions:



                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith(theArray).then(results => {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }








                        share|improve this answer



















                        • 1




                          Could you explain how the if (--expecting === 0) part of the code works please? The callback version of your solution is working great for me, I just don't understand how, with that statement, you are checking the number of responses completed. Appreciate it's just lack of knowledge on my part. Is there an alternative way that check could be written?
                          – Sarah
                          May 28 '17 at 10:21












                        • @Sarah: expecting starts out with the value of array.length, which is how many requests we're going to make. We know the callback won't be called until all of those requests are started. In the callback, if (--expecting === 0) does this: 1. Decrements expecting (we've received a response, so we're expecting one fewer response) and if the value after the decrement is 0 (we're not expecting any more responses), we're done!
                          – T.J. Crowder
                          May 28 '17 at 18:31













                        up vote
                        101
                        down vote










                        up vote
                        101
                        down vote









                        Most of the answers here give useful suggestions for when you have a single async operation, but sometimes, this comes up when you need to do an asynchronous operation for each entry in an array or other list-like structure. The temptation is to do this:



                        // WRONG
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log(results); // E.g., using them, returning them, etc.


                        Example:






                        // WRONG
                        var theArray = [1, 2, 3];
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log("Results:", results); // E.g., using them, returning them, etc.

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        The reason that doesn't work is that the callbacks from doSomethingAsync haven't run yet by the time you're trying to use the results.



                        So, if you have an array (or list of some kind) and want to do async operations for each entry, you have two options: Do the operations in parallel (overlapping), or in series (one after another in sequence).



                        Parallel



                        You can start all of them and keep track of how many callbacks you're expecting, and then use the results when you've gotten that many callbacks:



                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });


                        Example:






                        var theArray = [1, 2, 3];
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (We could do away with expecting and just use results.length === theArray.length, but that leaves us open to the possibility that theArray is changed while the calls are outstanding...)



                        Notice how we use the index from forEach to save the result in results in the same position as the entry it relates to, even if the results arrive out of order (since async calls don't necessarily complete in the order in which they were started).



                        But what if you need to return those results from a function? As the other answers have pointed out, you can't; you have to have your function accept and call a callback (or return a Promise). Here's a callback version:



                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith(theArray, function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        Or here's a version returning a Promise instead:



                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Of course, if doSomethingAsync passed us errors, we'd use reject to reject the promise when we got an error.)



                        Example:






                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (Or alternately, you could make a wrapper for doSomethingAsync that returns a promise, and then do the below...)



                        If doSomethingAsync gives you a Promise, you can use Promise.all:



                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        Note that Promise.all resolves its promise with an array of the results of all of the promises you give it when they are all resolved, or rejects its promise when the first of the promises you give it rejects.



                        Series



                        Suppose you don't want the operations to be in parallel? If you want to run them one after another, you need to wait for each operation to complete before you start the next. Here's an example of a function that does that and calls a callback with the result:



                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith(theArray, function(results) {
                        console.log("Results:", results);
                        });


                        (Since we're doing the work in series, we can just use results.push(result) since we know we won't get results out of order. In the above we could have used results[index] = result;, but in some of the following examples we don't have an index to use.)



                        Example:






                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (Or, again, build a wrapper for doSomethingAsync that gives you a promise and do the below...)



                        If doSomethingAsync gives you a Promise, if you can use ES2017+ syntax (perhaps with a transpiler like Babel), you can use an async function with for-of and await:



                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith(theArray).then(results => {
                        console.log("Results:", results);
                        });


                        Example:






                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        If you can't use ES2017+ syntax (yet), you can use a variation on the "Promise reduce" pattern (this is more complex than the usual Promise reduce because we're not passing the result from one into the next, but instead gathering up their results in an array):



                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        ...which is less cumbersome with ES2015+ arrow functions:



                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith(theArray).then(results => {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }








                        share|improve this answer














                        Most of the answers here give useful suggestions for when you have a single async operation, but sometimes, this comes up when you need to do an asynchronous operation for each entry in an array or other list-like structure. The temptation is to do this:



                        // WRONG
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log(results); // E.g., using them, returning them, etc.


                        Example:






                        // WRONG
                        var theArray = [1, 2, 3];
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log("Results:", results); // E.g., using them, returning them, etc.

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        The reason that doesn't work is that the callbacks from doSomethingAsync haven't run yet by the time you're trying to use the results.



                        So, if you have an array (or list of some kind) and want to do async operations for each entry, you have two options: Do the operations in parallel (overlapping), or in series (one after another in sequence).



                        Parallel



                        You can start all of them and keep track of how many callbacks you're expecting, and then use the results when you've gotten that many callbacks:



                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });


                        Example:






                        var theArray = [1, 2, 3];
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (We could do away with expecting and just use results.length === theArray.length, but that leaves us open to the possibility that theArray is changed while the calls are outstanding...)



                        Notice how we use the index from forEach to save the result in results in the same position as the entry it relates to, even if the results arrive out of order (since async calls don't necessarily complete in the order in which they were started).



                        But what if you need to return those results from a function? As the other answers have pointed out, you can't; you have to have your function accept and call a callback (or return a Promise). Here's a callback version:



                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith(theArray, function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        Or here's a version returning a Promise instead:



                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Of course, if doSomethingAsync passed us errors, we'd use reject to reject the promise when we got an error.)



                        Example:






                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (Or alternately, you could make a wrapper for doSomethingAsync that returns a promise, and then do the below...)



                        If doSomethingAsync gives you a Promise, you can use Promise.all:



                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        Note that Promise.all resolves its promise with an array of the results of all of the promises you give it when they are all resolved, or rejects its promise when the first of the promises you give it rejects.



                        Series



                        Suppose you don't want the operations to be in parallel? If you want to run them one after another, you need to wait for each operation to complete before you start the next. Here's an example of a function that does that and calls a callback with the result:



                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith(theArray, function(results) {
                        console.log("Results:", results);
                        });


                        (Since we're doing the work in series, we can just use results.push(result) since we know we won't get results out of order. In the above we could have used results[index] = result;, but in some of the following examples we don't have an index to use.)



                        Example:






                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        (Or, again, build a wrapper for doSomethingAsync that gives you a promise and do the below...)



                        If doSomethingAsync gives you a Promise, if you can use ES2017+ syntax (perhaps with a transpiler like Babel), you can use an async function with for-of and await:



                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith(theArray).then(results => {
                        console.log("Results:", results);
                        });


                        Example:






                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        If you can't use ES2017+ syntax (yet), you can use a variation on the "Promise reduce" pattern (this is more complex than the usual Promise reduce because we're not passing the result from one into the next, but instead gathering up their results in an array):



                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith(theArray).then(function(results) {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        ...which is less cumbersome with ES2015+ arrow functions:



                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith(theArray).then(results => {
                        console.log("Results:", results);
                        });


                        Example:






                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }








                        // WRONG
                        var theArray = [1, 2, 3];
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log("Results:", results); // E.g., using them, returning them, etc.

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        // WRONG
                        var theArray = [1, 2, 3];
                        var results = ;
                        theArray.forEach(function(entry) {
                        doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        });
                        console.log("Results:", results); // E.g., using them, returning them, etc.

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        var theArray = [1, 2, 3];
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        var theArray = [1, 2, 3];
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        console.log("Results:", results); // E.g., using the results
                        }
                        });
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        callback(results);
                        }
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray) {
                        return new Promise(function(resolve) {
                        var results = ;
                        var expecting = theArray.length;
                        theArray.forEach(function(entry, index) {
                        doSomethingAsync(entry, function(result) {
                        results[index] = result;
                        if (--expecting === 0) {
                        // Done!
                        resolve(results);
                        }
                        });
                        });
                        });
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray) {
                        return Promise.all(theArray.map(function(entry) {
                        return doSomethingAsync(entry, function(result) {
                        results.push(result);
                        });
                        }));
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray, callback) {
                        var results = ;
                        doOne(0);
                        function doOne(index) {
                        if (index < theArray.length) {
                        doSomethingAsync(theArray[index], function(result) {
                        results.push(result);
                        doOne(index + 1);
                        });
                        } else {
                        // Done!
                        callback(results);
                        }
                        }
                        }
                        doSomethingWith([1, 2, 3], function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value, callback) {
                        console.log("Starting async operation for " + value);
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        callback(value * 2);
                        }, Math.floor(Math.random() * 200));
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        async function doSomethingWith(theArray) {
                        const results = ;
                        for (const entry of theArray) {
                        results.push(await doSomethingAsync(entry));
                        }
                        return results;
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray) {
                        return theArray.reduce(function(p, entry) {
                        return p.then(function(results) {
                        return doSomethingAsync(entry).then(function(result) {
                        results.push(result);
                        return results;
                        });
                        });
                        }, Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }





                        function doSomethingWith(theArray) {
                        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
                        results.push(result);
                        return results;
                        })), Promise.resolve());
                        }
                        doSomethingWith([1, 2, 3]).then(function(results) {
                        console.log("Results:", results);
                        });

                        function doSomethingAsync(value) {
                        console.log("Starting async operation for " + value);
                        return new Promise(function(resolve) {
                        setTimeout(function() {
                        console.log("Completing async operation for " + value);
                        resolve(value * 2);
                        }, Math.floor(Math.random() * 200));
                        });
                        }

                        .as-console-wrapper {
                        max-height: 100% !important;
                        }






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Sep 13 '17 at 4:34









                        Joel Gritter

                        5731624




                        5731624










                        answered May 3 '17 at 16:59









                        T.J. Crowder

                        675k11911941289




                        675k11911941289








                        • 1




                          Could you explain how the if (--expecting === 0) part of the code works please? The callback version of your solution is working great for me, I just don't understand how, with that statement, you are checking the number of responses completed. Appreciate it's just lack of knowledge on my part. Is there an alternative way that check could be written?
                          – Sarah
                          May 28 '17 at 10:21












                        • @Sarah: expecting starts out with the value of array.length, which is how many requests we're going to make. We know the callback won't be called until all of those requests are started. In the callback, if (--expecting === 0) does this: 1. Decrements expecting (we've received a response, so we're expecting one fewer response) and if the value after the decrement is 0 (we're not expecting any more responses), we're done!
                          – T.J. Crowder
                          May 28 '17 at 18:31














                        • 1




                          Could you explain how the if (--expecting === 0) part of the code works please? The callback version of your solution is working great for me, I just don't understand how, with that statement, you are checking the number of responses completed. Appreciate it's just lack of knowledge on my part. Is there an alternative way that check could be written?
                          – Sarah
                          May 28 '17 at 10:21












                        • @Sarah: expecting starts out with the value of array.length, which is how many requests we're going to make. We know the callback won't be called until all of those requests are started. In the callback, if (--expecting === 0) does this: 1. Decrements expecting (we've received a response, so we're expecting one fewer response) and if the value after the decrement is 0 (we're not expecting any more responses), we're done!
                          – T.J. Crowder
                          May 28 '17 at 18:31








                        1




                        1




                        Could you explain how the if (--expecting === 0) part of the code works please? The callback version of your solution is working great for me, I just don't understand how, with that statement, you are checking the number of responses completed. Appreciate it's just lack of knowledge on my part. Is there an alternative way that check could be written?
                        – Sarah
                        May 28 '17 at 10:21






                        Could you explain how the if (--expecting === 0) part of the code works please? The callback version of your solution is working great for me, I just don't understand how, with that statement, you are checking the number of responses completed. Appreciate it's just lack of knowledge on my part. Is there an alternative way that check could be written?
                        – Sarah
                        May 28 '17 at 10:21














                        @Sarah: expecting starts out with the value of array.length, which is how many requests we're going to make. We know the callback won't be called until all of those requests are started. In the callback, if (--expecting === 0) does this: 1. Decrements expecting (we've received a response, so we're expecting one fewer response) and if the value after the decrement is 0 (we're not expecting any more responses), we're done!
                        – T.J. Crowder
                        May 28 '17 at 18:31




                        @Sarah: expecting starts out with the value of array.length, which is how many requests we're going to make. We know the callback won't be called until all of those requests are started. In the callback, if (--expecting === 0) does this: 1. Decrements expecting (we've received a response, so we're expecting one fewer response) and if the value after the decrement is 0 (we're not expecting any more responses), we're done!
                        – T.J. Crowder
                        May 28 '17 at 18:31










                        up vote
                        82
                        down vote













                        Have a look at this example:



                        var app = angular.module('plunker', );

                        app.controller('MainCtrl', function($scope,$http) {

                        var getJoke = function(){
                        return $http.get('http://api.icndb.com/jokes/random').then(function(res){
                        return res.data.value;
                        });
                        }

                        getJoke().then(function(res) {
                        console.log(res.joke);
                        });
                        });


                        As you can see getJoke is returning a resolved promise (it is resolved when returning res.data.value). So you wait until the $http.get request is completed and then console.log(res.joke) is executed (as a normal asynchronous flow).



                        This is the plnkr:



                        http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/



                        ES6 way (async - await)



                        (function(){
                        async function getJoke(){
                        let response = await fetch('http://api.icndb.com/jokes/random');
                        let data = await response.json();
                        return data.value;
                        }

                        getJoke().then((joke) => {
                        console.log(joke);
                        });
                        })();





                        share|improve this answer



























                          up vote
                          82
                          down vote













                          Have a look at this example:



                          var app = angular.module('plunker', );

                          app.controller('MainCtrl', function($scope,$http) {

                          var getJoke = function(){
                          return $http.get('http://api.icndb.com/jokes/random').then(function(res){
                          return res.data.value;
                          });
                          }

                          getJoke().then(function(res) {
                          console.log(res.joke);
                          });
                          });


                          As you can see getJoke is returning a resolved promise (it is resolved when returning res.data.value). So you wait until the $http.get request is completed and then console.log(res.joke) is executed (as a normal asynchronous flow).



                          This is the plnkr:



                          http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/



                          ES6 way (async - await)



                          (function(){
                          async function getJoke(){
                          let response = await fetch('http://api.icndb.com/jokes/random');
                          let data = await response.json();
                          return data.value;
                          }

                          getJoke().then((joke) => {
                          console.log(joke);
                          });
                          })();





                          share|improve this answer

























                            up vote
                            82
                            down vote










                            up vote
                            82
                            down vote









                            Have a look at this example:



                            var app = angular.module('plunker', );

                            app.controller('MainCtrl', function($scope,$http) {

                            var getJoke = function(){
                            return $http.get('http://api.icndb.com/jokes/random').then(function(res){
                            return res.data.value;
                            });
                            }

                            getJoke().then(function(res) {
                            console.log(res.joke);
                            });
                            });


                            As you can see getJoke is returning a resolved promise (it is resolved when returning res.data.value). So you wait until the $http.get request is completed and then console.log(res.joke) is executed (as a normal asynchronous flow).



                            This is the plnkr:



                            http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/



                            ES6 way (async - await)



                            (function(){
                            async function getJoke(){
                            let response = await fetch('http://api.icndb.com/jokes/random');
                            let data = await response.json();
                            return data.value;
                            }

                            getJoke().then((joke) => {
                            console.log(joke);
                            });
                            })();





                            share|improve this answer














                            Have a look at this example:



                            var app = angular.module('plunker', );

                            app.controller('MainCtrl', function($scope,$http) {

                            var getJoke = function(){
                            return $http.get('http://api.icndb.com/jokes/random').then(function(res){
                            return res.data.value;
                            });
                            }

                            getJoke().then(function(res) {
                            console.log(res.joke);
                            });
                            });


                            As you can see getJoke is returning a resolved promise (it is resolved when returning res.data.value). So you wait until the $http.get request is completed and then console.log(res.joke) is executed (as a normal asynchronous flow).



                            This is the plnkr:



                            http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/



                            ES6 way (async - await)



                            (function(){
                            async function getJoke(){
                            let response = await fetch('http://api.icndb.com/jokes/random');
                            let data = await response.json();
                            return data.value;
                            }

                            getJoke().then((joke) => {
                            console.log(joke);
                            });
                            })();






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 23 at 12:19

























                            answered Jun 2 '16 at 8:31









                            Francisco Carmona

                            1,18649




                            1,18649






















                                up vote
                                73
                                down vote













                                Another approach to return a value from an asynchronous function, is to pass in an object that will store the result from the asynchronous function.



                                Here is an example of the same:



                                var async = require("async");

                                // This wires up result back to the caller
                                var result = {};
                                var asyncTasks = ;
                                asyncTasks.push(function(_callback){
                                // some asynchronous operation
                                $.ajax({
                                url: '...',
                                success: function(response) {
                                result.response = response;
                                _callback();
                                }
                                });
                                });

                                async.parallel(asyncTasks, function(){
                                // result is available after performing asynchronous operation
                                console.log(result)
                                console.log('Done');
                                });


                                I am using the result object to store the value during the asynchronous operation. This allows the result be available even after the asynchronous job.



                                I use this approach a lot. I would be interested to know how well this approach works where wiring the result back through consecutive modules is involved.






                                share|improve this answer



















                                • 9




                                  There is nothing special about using an object here. It would work as well if you assigned he response directly to result. It works because you are reading the variable after the async function is complete.
                                  – Felix Kling
                                  Sep 2 '15 at 13:18















                                up vote
                                73
                                down vote













                                Another approach to return a value from an asynchronous function, is to pass in an object that will store the result from the asynchronous function.



                                Here is an example of the same:



                                var async = require("async");

                                // This wires up result back to the caller
                                var result = {};
                                var asyncTasks = ;
                                asyncTasks.push(function(_callback){
                                // some asynchronous operation
                                $.ajax({
                                url: '...',
                                success: function(response) {
                                result.response = response;
                                _callback();
                                }
                                });
                                });

                                async.parallel(asyncTasks, function(){
                                // result is available after performing asynchronous operation
                                console.log(result)
                                console.log('Done');
                                });


                                I am using the result object to store the value during the asynchronous operation. This allows the result be available even after the asynchronous job.



                                I use this approach a lot. I would be interested to know how well this approach works where wiring the result back through consecutive modules is involved.






                                share|improve this answer



















                                • 9




                                  There is nothing special about using an object here. It would work as well if you assigned he response directly to result. It works because you are reading the variable after the async function is complete.
                                  – Felix Kling
                                  Sep 2 '15 at 13:18













                                up vote
                                73
                                down vote










                                up vote
                                73
                                down vote









                                Another approach to return a value from an asynchronous function, is to pass in an object that will store the result from the asynchronous function.



                                Here is an example of the same:



                                var async = require("async");

                                // This wires up result back to the caller
                                var result = {};
                                var asyncTasks = ;
                                asyncTasks.push(function(_callback){
                                // some asynchronous operation
                                $.ajax({
                                url: '...',
                                success: function(response) {
                                result.response = response;
                                _callback();
                                }
                                });
                                });

                                async.parallel(asyncTasks, function(){
                                // result is available after performing asynchronous operation
                                console.log(result)
                                console.log('Done');
                                });


                                I am using the result object to store the value during the asynchronous operation. This allows the result be available even after the asynchronous job.



                                I use this approach a lot. I would be interested to know how well this approach works where wiring the result back through consecutive modules is involved.






                                share|improve this answer














                                Another approach to return a value from an asynchronous function, is to pass in an object that will store the result from the asynchronous function.



                                Here is an example of the same:



                                var async = require("async");

                                // This wires up result back to the caller
                                var result = {};
                                var asyncTasks = ;
                                asyncTasks.push(function(_callback){
                                // some asynchronous operation
                                $.ajax({
                                url: '...',
                                success: function(response) {
                                result.response = response;
                                _callback();
                                }
                                });
                                });

                                async.parallel(asyncTasks, function(){
                                // result is available after performing asynchronous operation
                                console.log(result)
                                console.log('Done');
                                });


                                I am using the result object to store the value during the asynchronous operation. This allows the result be available even after the asynchronous job.



                                I use this approach a lot. I would be interested to know how well this approach works where wiring the result back through consecutive modules is involved.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Dec 17 '16 at 12:55









                                Peter Mortensen

                                13.4k1983111




                                13.4k1983111










                                answered Sep 2 '15 at 12:54









                                jsbisht

                                3,84553142




                                3,84553142








                                • 9




                                  There is nothing special about using an object here. It would work as well if you assigned he response directly to result. It works because you are reading the variable after the async function is complete.
                                  – Felix Kling
                                  Sep 2 '15 at 13:18














                                • 9




                                  There is nothing special about using an object here. It would work as well if you assigned he response directly to result. It works because you are reading the variable after the async function is complete.
                                  – Felix Kling
                                  Sep 2 '15 at 13:18








                                9




                                9




                                There is nothing special about using an object here. It would work as well if you assigned he response directly to result. It works because you are reading the variable after the async function is complete.
                                – Felix Kling
                                Sep 2 '15 at 13:18




                                There is nothing special about using an object here. It would work as well if you assigned he response directly to result. It works because you are reading the variable after the async function is complete.
                                – Felix Kling
                                Sep 2 '15 at 13:18










                                up vote
                                68
                                down vote













                                This is one of the places which two ways data binding that's used in many new JavaScript frameworks will work greatly for you...



                                So if you are using Angular, React or any other frameworks which do two ways data binding, this issue is simply fixed for you, so in easy word, your result is undefined at the first stage, so you have got result = undefined before you receive the data, then as soon as you get the result, it will updated and get assigned to the new value which is respond of your Ajax call...



                                But how you can do it in pure javascript or jQuery for example as you asked in this question?



                                You can use a callback, promise and recently observable to handle it for you, for example in promises we have some function like success() or then() which will be executed when your data is ready for you, same with callback or subscribe function on observable.



                                For example in your case which you are using jQuery, you can do something like this:



                                $(document).ready(function(){
                                function foo() {
                                $.ajax({url: "api/data", success: function(data){
                                fooDone(data); //after we have data, we pass it to fooDone
                                }});
                                };

                                function fooDone(data) {
                                console.log(data); //fooDone has the data and console.log it
                                };

                                foo(); //call happens here
                                });


                                For more information study about promises and observables which are newer ways to do this async stuffs.






                                share|improve this answer























                                • This is fine at global scope, but in some module context you probably want to ensure right context for the callback e.g. $.ajax({url: "api/data", success: fooDone.bind(this)});
                                  – steve.sims
                                  Jul 24 '17 at 6:14








                                • 5




                                  This is actually incorrect as React is one-way data binding
                                  – Matthew Brent
                                  May 4 at 15:57










                                • @MatthewBrent you are not wrong, but not right also, React props are object and if changed, they change throughout the application, but its not a way that React developer recommend to use it...
                                  – Alireza
                                  May 14 at 7:34















                                up vote
                                68
                                down vote













                                This is one of the places which two ways data binding that's used in many new JavaScript frameworks will work greatly for you...



                                So if you are using Angular, React or any other frameworks which do two ways data binding, this issue is simply fixed for you, so in easy word, your result is undefined at the first stage, so you have got result = undefined before you receive the data, then as soon as you get the result, it will updated and get assigned to the new value which is respond of your Ajax call...



                                But how you can do it in pure javascript or jQuery for example as you asked in this question?



                                You can use a callback, promise and recently observable to handle it for you, for example in promises we have some function like success() or then() which will be executed when your data is ready for you, same with callback or subscribe function on observable.



                                For example in your case which you are using jQuery, you can do something like this:



                                $(document).ready(function(){
                                function foo() {
                                $.ajax({url: "api/data", success: function(data){
                                fooDone(data); //after we have data, we pass it to fooDone
                                }});
                                };

                                function fooDone(data) {
                                console.log(data); //fooDone has the data and console.log it
                                };

                                foo(); //call happens here
                                });


                                For more information study about promises and observables which are newer ways to do this async stuffs.






                                share|improve this answer























                                • This is fine at global scope, but in some module context you probably want to ensure right context for the callback e.g. $.ajax({url: "api/data", success: fooDone.bind(this)});
                                  – steve.sims
                                  Jul 24 '17 at 6:14








                                • 5




                                  This is actually incorrect as React is one-way data binding
                                  – Matthew Brent
                                  May 4 at 15:57










                                • @MatthewBrent you are not wrong, but not right also, React props are object and if changed, they change throughout the application, but its not a way that React developer recommend to use it...
                                  – Alireza
                                  May 14 at 7:34













                                up vote
                                68
                                down vote










                                up vote
                                68
                                down vote









                                This is one of the places which two ways data binding that's used in many new JavaScript frameworks will work greatly for you...



                                So if you are using Angular, React or any other frameworks which do two ways data binding, this issue is simply fixed for you, so in easy word, your result is undefined at the first stage, so you have got result = undefined before you receive the data, then as soon as you get the result, it will updated and get assigned to the new value which is respond of your Ajax call...



                                But how you can do it in pure javascript or jQuery for example as you asked in this question?



                                You can use a callback, promise and recently observable to handle it for you, for example in promises we have some function like success() or then() which will be executed when your data is ready for you, same with callback or subscribe function on observable.



                                For example in your case which you are using jQuery, you can do something like this:



                                $(document).ready(function(){
                                function foo() {
                                $.ajax({url: "api/data", success: function(data){
                                fooDone(data); //after we have data, we pass it to fooDone
                                }});
                                };

                                function fooDone(data) {
                                console.log(data); //fooDone has the data and console.log it
                                };

                                foo(); //call happens here
                                });


                                For more information study about promises and observables which are newer ways to do this async stuffs.






                                share|improve this answer














                                This is one of the places which two ways data binding that's used in many new JavaScript frameworks will work greatly for you...



                                So if you are using Angular, React or any other frameworks which do two ways data binding, this issue is simply fixed for you, so in easy word, your result is undefined at the first stage, so you have got result = undefined before you receive the data, then as soon as you get the result, it will updated and get assigned to the new value which is respond of your Ajax call...



                                But how you can do it in pure javascript or jQuery for example as you asked in this question?



                                You can use a callback, promise and recently observable to handle it for you, for example in promises we have some function like success() or then() which will be executed when your data is ready for you, same with callback or subscribe function on observable.



                                For example in your case which you are using jQuery, you can do something like this:



                                $(document).ready(function(){
                                function foo() {
                                $.ajax({url: "api/data", success: function(data){
                                fooDone(data); //after we have data, we pass it to fooDone
                                }});
                                };

                                function fooDone(data) {
                                console.log(data); //fooDone has the data and console.log it
                                };

                                foo(); //call happens here
                                });


                                For more information study about promises and observables which are newer ways to do this async stuffs.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited May 25 at 13:46

























                                answered May 24 '17 at 9:38









                                Alireza

                                44.6k12163119




                                44.6k12163119












                                • This is fine at global scope, but in some module context you probably want to ensure right context for the callback e.g. $.ajax({url: "api/data", success: fooDone.bind(this)});
                                  – steve.sims
                                  Jul 24 '17 at 6:14








                                • 5




                                  This is actually incorrect as React is one-way data binding
                                  – Matthew Brent
                                  May 4 at 15:57










                                • @MatthewBrent you are not wrong, but not right also, React props are object and if changed, they change throughout the application, but its not a way that React developer recommend to use it...
                                  – Alireza
                                  May 14 at 7:34


















                                • This is fine at global scope, but in some module context you probably want to ensure right context for the callback e.g. $.ajax({url: "api/data", success: fooDone.bind(this)});
                                  – steve.sims
                                  Jul 24 '17 at 6:14








                                • 5




                                  This is actually incorrect as React is one-way data binding
                                  – Matthew Brent
                                  May 4 at 15:57










                                • @MatthewBrent you are not wrong, but not right also, React props are object and if changed, they change throughout the application, but its not a way that React developer recommend to use it...
                                  – Alireza
                                  May 14 at 7:34
















                                This is fine at global scope, but in some module context you probably want to ensure right context for the callback e.g. $.ajax({url: "api/data", success: fooDone.bind(this)});
                                – steve.sims
                                Jul 24 '17 at 6:14






                                This is fine at global scope, but in some module context you probably want to ensure right context for the callback e.g. $.ajax({url: "api/data", success: fooDone.bind(this)});
                                – steve.sims
                                Jul 24 '17 at 6:14






                                5




                                5




                                This is actually incorrect as React is one-way data binding
                                – Matthew Brent
                                May 4 at 15:57




                                This is actually incorrect as React is one-way data binding
                                – Matthew Brent
                                May 4 at 15:57












                                @MatthewBrent you are not wrong, but not right also, React props are object and if changed, they change throughout the application, but its not a way that React developer recommend to use it...
                                – Alireza
                                May 14 at 7:34




                                @MatthewBrent you are not wrong, but not right also, React props are object and if changed, they change throughout the application, but its not a way that React developer recommend to use it...
                                – Alireza
                                May 14 at 7:34










                                up vote
                                64
                                down vote













                                While promises and callbacks work fine in many situations, it is a pain in the rear to express something like:



                                if (!name) {
                                name = async1();
                                }
                                async2(name);


                                You'd end up going through async1; check if name is undefined or not and call the callback accordingly.



                                async1(name, callback) {
                                if (name)
                                callback(name)
                                else {
                                doSomething(callback)
                                }
                                }

                                async1(name, async2)


                                While it is okay in small examples it gets annoying when you have a lot of similar cases and error handling involved.



                                Fibers helps in solving the issue.



                                var Fiber = require('fibers')

                                function async1(container) {
                                var current = Fiber.current
                                var result
                                doSomething(function(name) {
                                result = name
                                fiber.run()
                                })
                                Fiber.yield()
                                return result
                                }

                                Fiber(function() {
                                var name
                                if (!name) {
                                name = async1()
                                }
                                async2(name)
                                // Make any number of async calls from here
                                }


                                You can checkout the project here.






                                share|improve this answer























                                • @recurf - It's not my project. You could try using their issue tracker.
                                  – rohithpr
                                  Jan 20 '17 at 15:22










                                • is this similar to generator functions? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…*
                                  – Emanegux
                                  Jun 7 '17 at 3:19










                                • Is this still relevant?
                                  – Aluan Haddad
                                  Mar 18 at 19:43










                                • You can make use of async-await if you're using some of the newest versions of node. If someone is stuck with older versions they can use this method.
                                  – rohithpr
                                  Mar 20 at 8:18

















                                up vote
                                64
                                down vote













                                While promises and callbacks work fine in many situations, it is a pain in the rear to express something like:



                                if (!name) {
                                name = async1();
                                }
                                async2(name);


                                You'd end up going through async1; check if name is undefined or not and call the callback accordingly.



                                async1(name, callback) {
                                if (name)
                                callback(name)
                                else {
                                doSomething(callback)
                                }
                                }

                                async1(name, async2)


                                While it is okay in small examples it gets annoying when you have a lot of similar cases and error handling involved.



                                Fibers helps in solving the issue.



                                var Fiber = require('fibers')

                                function async1(container) {
                                var current = Fiber.current
                                var result
                                doSomething(function(name) {
                                result = name
                                fiber.run()
                                })
                                Fiber.yield()
                                return result
                                }

                                Fiber(function() {
                                var name
                                if (!name) {
                                name = async1()
                                }
                                async2(name)
                                // Make any number of async calls from here
                                }


                                You can checkout the project here.






                                share|improve this answer























                                • @recurf - It's not my project. You could try using their issue tracker.
                                  – rohithpr
                                  Jan 20 '17 at 15:22










                                • is this similar to generator functions? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…*
                                  – Emanegux
                                  Jun 7 '17 at 3:19










                                • Is this still relevant?
                                  – Aluan Haddad
                                  Mar 18 at 19:43










                                • You can make use of async-await if you're using some of the newest versions of node. If someone is stuck with older versions they can use this method.
                                  – rohithpr
                                  Mar 20 at 8:18















                                up vote
                                64
                                down vote










                                up vote
                                64
                                down vote









                                While promises and callbacks work fine in many situations, it is a pain in the rear to express something like:



                                if (!name) {
                                name = async1();
                                }
                                async2(name);


                                You'd end up going through async1; check if name is undefined or not and call the callback accordingly.



                                async1(name, callback) {
                                if (name)
                                callback(name)
                                else {
                                doSomething(callback)
                                }
                                }

                                async1(name, async2)


                                While it is okay in small examples it gets annoying when you have a lot of similar cases and error handling involved.



                                Fibers helps in solving the issue.



                                var Fiber = require('fibers')

                                function async1(container) {
                                var current = Fiber.current
                                var result
                                doSomething(function(name) {
                                result = name
                                fiber.run()
                                })
                                Fiber.yield()
                                return result
                                }

                                Fiber(function() {
                                var name
                                if (!name) {
                                name = async1()
                                }
                                async2(name)
                                // Make any number of async calls from here
                                }


                                You can checkout the project here.






                                share|improve this answer














                                While promises and callbacks work fine in many situations, it is a pain in the rear to express something like:



                                if (!name) {
                                name = async1();
                                }
                                async2(name);


                                You'd end up going through async1; check if name is undefined or not and call the callback accordingly.



                                async1(name, callback) {
                                if (name)
                                callback(name)
                                else {
                                doSomething(callback)
                                }
                                }

                                async1(name, async2)


                                While it is okay in small examples it gets annoying when you have a lot of similar cases and error handling involved.



                                Fibers helps in solving the issue.



                                var Fiber = require('fibers')

                                function async1(container) {
                                var current = Fiber.current
                                var result
                                doSomething(function(name) {
                                result = name
                                fiber.run()
                                })
                                Fiber.yield()
                                return result
                                }

                                Fiber(function() {
                                var name
                                if (!name) {
                                name = async1()
                                }
                                async2(name)
                                // Make any number of async calls from here
                                }


                                You can checkout the project here.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited May 9 '16 at 13:02

























                                answered Jan 25 '16 at 17:43









                                rohithpr

                                2,51722137




                                2,51722137












                                • @recurf - It's not my project. You could try using their issue tracker.
                                  – rohithpr
                                  Jan 20 '17 at 15:22










                                • is this similar to generator functions? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…*
                                  – Emanegux
                                  Jun 7 '17 at 3:19










                                • Is this still relevant?
                                  – Aluan Haddad
                                  Mar 18 at 19:43










                                • You can make use of async-await if you're using some of the newest versions of node. If someone is stuck with older versions they can use this method.
                                  – rohithpr
                                  Mar 20 at 8:18




















                                • @recurf - It's not my project. You could try using their issue tracker.
                                  – rohithpr
                                  Jan 20 '17 at 15:22










                                • is this similar to generator functions? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…*
                                  – Emanegux
                                  Jun 7 '17 at 3:19










                                • Is this still relevant?
                                  – Aluan Haddad
                                  Mar 18 at 19:43










                                • You can make use of async-await if you're using some of the newest versions of node. If someone is stuck with older versions they can use this method.
                                  – rohithpr
                                  Mar 20 at 8:18


















                                @recurf - It's not my project. You could try using their issue tracker.
                                – rohithpr
                                Jan 20 '17 at 15:22




                                @recurf - It's not my project. You could try using their issue tracker.
                                – rohithpr
                                Jan 20 '17 at 15:22












                                is this similar to generator functions? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…*
                                – Emanegux
                                Jun 7 '17 at 3:19




                                is this similar to generator functions? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…*
                                – Emanegux
                                Jun 7 '17 at 3:19












                                Is this still relevant?
                                – Aluan Haddad
                                Mar 18 at 19:43




                                Is this still relevant?
                                – Aluan Haddad
                                Mar 18 at 19:43












                                You can make use of async-await if you're using some of the newest versions of node. If someone is stuck with older versions they can use this method.
                                – rohithpr
                                Mar 20 at 8:18






                                You can make use of async-await if you're using some of the newest versions of node. If someone is stuck with older versions they can use this method.
                                – rohithpr
                                Mar 20 at 8:18












                                up vote
                                61
                                down vote













                                Short answer is, you have to implement a callback like this:



                                function callback(response) {
                                // Here you can do what ever you want with the response object.
                                console.log(response);
                                }

                                $.ajax({
                                url: "...",
                                success: callback
                                });





                                share|improve this answer



























                                  up vote
                                  61
                                  down vote













                                  Short answer is, you have to implement a callback like this:



                                  function callback(response) {
                                  // Here you can do what ever you want with the response object.
                                  console.log(response);
                                  }

                                  $.ajax({
                                  url: "...",
                                  success: callback
                                  });





                                  share|improve this answer

























                                    up vote
                                    61
                                    down vote










                                    up vote
                                    61
                                    down vote









                                    Short answer is, you have to implement a callback like this:



                                    function callback(response) {
                                    // Here you can do what ever you want with the response object.
                                    console.log(response);
                                    }

                                    $.ajax({
                                    url: "...",
                                    success: callback
                                    });





                                    share|improve this answer














                                    Short answer is, you have to implement a callback like this:



                                    function callback(response) {
                                    // Here you can do what ever you want with the response object.
                                    console.log(response);
                                    }

                                    $.ajax({
                                    url: "...",
                                    success: callback
                                    });






                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Aug 9 '16 at 18:32

























                                    answered Apr 22 '16 at 14:47









                                    Pablo Matias Gomez

                                    3,59442255




                                    3,59442255






















                                        up vote
                                        58
                                        down vote













                                        The following example I have written shows how to




                                        • Handle asynchronous HTTP calls;

                                        • Wait for response from each API call;

                                        • Use Promise pattern;

                                        • Use Promise.all pattern to join multiple HTTP calls;


                                        This working example is self-contained. It will define a simple request object that uses the window XMLHttpRequest object to make calls. It will define a simple function to wait for a bunch of promises to be completed.



                                        Context. The example is querying the Spotify Web API endpoint in order to search for playlist objects for a given set of query strings:



                                        [
                                        "search?type=playlist&q=%22doom%20metal%22",
                                        "search?type=playlist&q=Adele"
                                        ]


                                        For each item, a new Promise will fire a block - ExecutionBlock, parse the result, schedule a new set of promises based on the result array, that is a list of Spotify user objects and execute the new HTTP call within the ExecutionProfileBlock asynchronously.



                                        You can then see a nested Promise structure, that lets you spawn multiple and completely asynchronous nested HTTP calls, and join the results from each subset of calls through Promise.all.



                                        NOTE
                                        Recent Spotify search APIs will require an access token to be specified in the request headers:



                                        -H "Authorization: Bearer {your access token}" 


                                        So, you to run the following example you need to put your access token in the request headers:






                                        var spotifyAccessToken = "YourSpotifyAccessToken";
                                        var console = {
                                        log: function(s) {
                                        document.getElementById("console").innerHTML += s + "<br/>"
                                        }
                                        }

                                        // Simple XMLHttpRequest
                                        // based on https://davidwalsh.name/xmlhttprequest
                                        SimpleRequest = {
                                        call: function(what, response) {
                                        var request;
                                        if (window.XMLHttpRequest) { // Mozilla, Safari, ...
                                        request = new XMLHttpRequest();
                                        } else if (window.ActiveXObject) { // Internet Explorer
                                        try {
                                        request = new ActiveXObject('Msxml2.XMLHTTP');
                                        }
                                        catch (e) {
                                        try {
                                        request = new ActiveXObject('Microsoft.XMLHTTP');
                                        } catch (e) {}
                                        }
                                        }

                                        // State changes
                                        request.onreadystatechange = function() {
                                        if (request.readyState === 4) { // Done
                                        if (request.status === 200) { // Complete
                                        response(request.responseText)
                                        }
                                        else
                                        response();
                                        }
                                        }
                                        request.open('GET', what, true);
                                        request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
                                        request.send(null);
                                        }
                                        }

                                        //PromiseAll
                                        var promiseAll = function(items, block, done, fail) {
                                        var self = this;
                                        var promises = ,
                                        index = 0;
                                        items.forEach(function(item) {
                                        promises.push(function(item, i) {
                                        return new Promise(function(resolve, reject) {
                                        if (block) {
                                        block.apply(this, [item, index, resolve, reject]);
                                        }
                                        });
                                        }(item, ++index))
                                        });
                                        Promise.all(promises).then(function AcceptHandler(results) {
                                        if (done) done(results);
                                        }, function ErrorHandler(error) {
                                        if (fail) fail(error);
                                        });
                                        }; //promiseAll

                                        // LP: deferred execution block
                                        var ExecutionBlock = function(item, index, resolve, reject) {
                                        var url = "https://api.spotify.com/v1/"
                                        url += item;
                                        console.log( url )
                                        SimpleRequest.call(url, function(result) {
                                        if (result) {

                                        var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
                                        return item.owner.href;
                                        })
                                        resolve(profileUrls);
                                        }
                                        else {
                                        reject(new Error("call error"));
                                        }
                                        })
                                        }

                                        arr = [
                                        "search?type=playlist&q=%22doom%20metal%22",
                                        "search?type=playlist&q=Adele"
                                        ]

                                        promiseAll(arr, function(item, index, resolve, reject) {
                                        console.log("Making request [" + index + "]")
                                        ExecutionBlock(item, index, resolve, reject);
                                        }, function(results) { // Aggregated results

                                        console.log("All profiles received " + results.length);
                                        //console.log(JSON.stringify(results[0], null, 2));

                                        ///// promiseall again

                                        var ExecutionProfileBlock = function(item, index, resolve, reject) {
                                        SimpleRequest.call(item, function(result) {
                                        if (result) {
                                        var obj = JSON.parse(result);
                                        resolve({
                                        name: obj.display_name,
                                        followers: obj.followers.total,
                                        url: obj.href
                                        });
                                        } //result
                                        })
                                        } //ExecutionProfileBlock

                                        promiseAll(results[0], function(item, index, resolve, reject) {
                                        //console.log("Making request [" + index + "] " + item)
                                        ExecutionProfileBlock(item, index, resolve, reject);
                                        }, function(results) { // aggregated results
                                        console.log("All response received " + results.length);
                                        console.log(JSON.stringify(results, null, 2));
                                        }

                                        , function(error) { // Error
                                        console.log(error);
                                        })

                                        /////

                                        },
                                        function(error) { // Error
                                        console.log(error);
                                        });

                                        <div id="console" />





                                        I have extensively discussed this solution here.






                                        share|improve this answer



























                                          up vote
                                          58
                                          down vote













                                          The following example I have written shows how to




                                          • Handle asynchronous HTTP calls;

                                          • Wait for response from each API call;

                                          • Use Promise pattern;

                                          • Use Promise.all pattern to join multiple HTTP calls;


                                          This working example is self-contained. It will define a simple request object that uses the window XMLHttpRequest object to make calls. It will define a simple function to wait for a bunch of promises to be completed.



                                          Context. The example is querying the Spotify Web API endpoint in order to search for playlist objects for a given set of query strings:



                                          [
                                          "search?type=playlist&q=%22doom%20metal%22",
                                          "search?type=playlist&q=Adele"
                                          ]


                                          For each item, a new Promise will fire a block - ExecutionBlock, parse the result, schedule a new set of promises based on the result array, that is a list of Spotify user objects and execute the new HTTP call within the ExecutionProfileBlock asynchronously.



                                          You can then see a nested Promise structure, that lets you spawn multiple and completely asynchronous nested HTTP calls, and join the results from each subset of calls through Promise.all.



                                          NOTE
                                          Recent Spotify search APIs will require an access token to be specified in the request headers:



                                          -H "Authorization: Bearer {your access token}" 


                                          So, you to run the following example you need to put your access token in the request headers:






                                          var spotifyAccessToken = "YourSpotifyAccessToken";
                                          var console = {
                                          log: function(s) {
                                          document.getElementById("console").innerHTML += s + "<br/>"
                                          }
                                          }

                                          // Simple XMLHttpRequest
                                          // based on https://davidwalsh.name/xmlhttprequest
                                          SimpleRequest = {
                                          call: function(what, response) {
                                          var request;
                                          if (window.XMLHttpRequest) { // Mozilla, Safari, ...
                                          request = new XMLHttpRequest();
                                          } else if (window.ActiveXObject) { // Internet Explorer
                                          try {
                                          request = new ActiveXObject('Msxml2.XMLHTTP');
                                          }
                                          catch (e) {
                                          try {
                                          request = new ActiveXObject('Microsoft.XMLHTTP');
                                          } catch (e) {}
                                          }
                                          }

                                          // State changes
                                          request.onreadystatechange = function() {
                                          if (request.readyState === 4) { // Done
                                          if (request.status === 200) { // Complete
                                          response(request.responseText)
                                          }
                                          else
                                          response();
                                          }
                                          }
                                          request.open('GET', what, true);
                                          request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
                                          request.send(null);
                                          }
                                          }

                                          //PromiseAll
                                          var promiseAll = function(items, block, done, fail) {
                                          var self = this;
                                          var promises = ,
                                          index = 0;
                                          items.forEach(function(item) {
                                          promises.push(function(item, i) {
                                          return new Promise(function(resolve, reject) {
                                          if (block) {
                                          block.apply(this, [item, index, resolve, reject]);
                                          }
                                          });
                                          }(item, ++index))
                                          });
                                          Promise.all(promises).then(function AcceptHandler(results) {
                                          if (done) done(results);
                                          }, function ErrorHandler(error) {
                                          if (fail) fail(error);
                                          });
                                          }; //promiseAll

                                          // LP: deferred execution block
                                          var ExecutionBlock = function(item, index, resolve, reject) {
                                          var url = "https://api.spotify.com/v1/"
                                          url += item;
                                          console.log( url )
                                          SimpleRequest.call(url, function(result) {
                                          if (result) {

                                          var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
                                          return item.owner.href;
                                          })
                                          resolve(profileUrls);
                                          }
                                          else {
                                          reject(new Error("call error"));
                                          }
                                          })
                                          }

                                          arr = [
                                          "search?type=playlist&q=%22doom%20metal%22",
                                          "search?type=playlist&q=Adele"
                                          ]

                                          promiseAll(arr, function(item, index, resolve, reject) {
                                          console.log("Making request [" + index + "]")
                                          ExecutionBlock(item, index, resolve, reject);
                                          }, function(results) { // Aggregated results

                                          console.log("All profiles received " + results.length);
                                          //console.log(JSON.stringify(results[0], null, 2));

                                          ///// promiseall again

                                          var ExecutionProfileBlock = function(item, index, resolve, reject) {
                                          SimpleRequest.call(item, function(result) {
                                          if (result) {
                                          var obj = JSON.parse(result);
                                          resolve({
                                          name: obj.display_name,
                                          followers: obj.followers.total,
                                          url: obj.href
                                          });
                                          } //result
                                          })
                                          } //ExecutionProfileBlock

                                          promiseAll(results[0], function(item, index, resolve, reject) {
                                          //console.log("Making request [" + index + "] " + item)
                                          ExecutionProfileBlock(item, index, resolve, reject);
                                          }, function(results) { // aggregated results
                                          console.log("All response received " + results.length);
                                          console.log(JSON.stringify(results, null, 2));
                                          }

                                          , function(error) { // Error
                                          console.log(error);
                                          })

                                          /////

                                          },
                                          function(error) { // Error
                                          console.log(error);
                                          });

                                          <div id="console" />





                                          I have extensively discussed this solution here.






                                          share|improve this answer

























                                            up vote
                                            58
                                            down vote










                                            up vote
                                            58
                                            down vote









                                            The following example I have written shows how to




                                            • Handle asynchronous HTTP calls;

                                            • Wait for response from each API call;

                                            • Use Promise pattern;

                                            • Use Promise.all pattern to join multiple HTTP calls;


                                            This working example is self-contained. It will define a simple request object that uses the window XMLHttpRequest object to make calls. It will define a simple function to wait for a bunch of promises to be completed.



                                            Context. The example is querying the Spotify Web API endpoint in order to search for playlist objects for a given set of query strings:



                                            [
                                            "search?type=playlist&q=%22doom%20metal%22",
                                            "search?type=playlist&q=Adele"
                                            ]


                                            For each item, a new Promise will fire a block - ExecutionBlock, parse the result, schedule a new set of promises based on the result array, that is a list of Spotify user objects and execute the new HTTP call within the ExecutionProfileBlock asynchronously.



                                            You can then see a nested Promise structure, that lets you spawn multiple and completely asynchronous nested HTTP calls, and join the results from each subset of calls through Promise.all.



                                            NOTE
                                            Recent Spotify search APIs will require an access token to be specified in the request headers:



                                            -H "Authorization: Bearer {your access token}" 


                                            So, you to run the following example you need to put your access token in the request headers:






                                            var spotifyAccessToken = "YourSpotifyAccessToken";
                                            var console = {
                                            log: function(s) {
                                            document.getElementById("console").innerHTML += s + "<br/>"
                                            }
                                            }

                                            // Simple XMLHttpRequest
                                            // based on https://davidwalsh.name/xmlhttprequest
                                            SimpleRequest = {
                                            call: function(what, response) {
                                            var request;
                                            if (window.XMLHttpRequest) { // Mozilla, Safari, ...
                                            request = new XMLHttpRequest();
                                            } else if (window.ActiveXObject) { // Internet Explorer
                                            try {
                                            request = new ActiveXObject('Msxml2.XMLHTTP');
                                            }
                                            catch (e) {
                                            try {
                                            request = new ActiveXObject('Microsoft.XMLHTTP');
                                            } catch (e) {}
                                            }
                                            }

                                            // State changes
                                            request.onreadystatechange = function() {
                                            if (request.readyState === 4) { // Done
                                            if (request.status === 200) { // Complete
                                            response(request.responseText)
                                            }
                                            else
                                            response();
                                            }
                                            }
                                            request.open('GET', what, true);
                                            request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
                                            request.send(null);
                                            }
                                            }

                                            //PromiseAll
                                            var promiseAll = function(items, block, done, fail) {
                                            var self = this;
                                            var promises = ,
                                            index = 0;
                                            items.forEach(function(item) {
                                            promises.push(function(item, i) {
                                            return new Promise(function(resolve, reject) {
                                            if (block) {
                                            block.apply(this, [item, index, resolve, reject]);
                                            }
                                            });
                                            }(item, ++index))
                                            });
                                            Promise.all(promises).then(function AcceptHandler(results) {
                                            if (done) done(results);
                                            }, function ErrorHandler(error) {
                                            if (fail) fail(error);
                                            });
                                            }; //promiseAll

                                            // LP: deferred execution block
                                            var ExecutionBlock = function(item, index, resolve, reject) {
                                            var url = "https://api.spotify.com/v1/"
                                            url += item;
                                            console.log( url )
                                            SimpleRequest.call(url, function(result) {
                                            if (result) {

                                            var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
                                            return item.owner.href;
                                            })
                                            resolve(profileUrls);
                                            }
                                            else {
                                            reject(new Error("call error"));
                                            }
                                            })
                                            }

                                            arr = [
                                            "search?type=playlist&q=%22doom%20metal%22",
                                            "search?type=playlist&q=Adele"
                                            ]

                                            promiseAll(arr, function(item, index, resolve, reject) {
                                            console.log("Making request [" + index + "]")
                                            ExecutionBlock(item, index, resolve, reject);
                                            }, function(results) { // Aggregated results

                                            console.log("All profiles received " + results.length);
                                            //console.log(JSON.stringify(results[0], null, 2));

                                            ///// promiseall again

                                            var ExecutionProfileBlock = function(item, index, resolve, reject) {
                                            SimpleRequest.call(item, function(result) {
                                            if (result) {
                                            var obj = JSON.parse(result);
                                            resolve({
                                            name: obj.display_name,
                                            followers: obj.followers.total,
                                            url: obj.href
                                            });
                                            } //result
                                            })
                                            } //ExecutionProfileBlock

                                            promiseAll(results[0], function(item, index, resolve, reject) {
                                            //console.log("Making request [" + index + "] " + item)
                                            ExecutionProfileBlock(item, index, resolve, reject);
                                            }, function(results) { // aggregated results
                                            console.log("All response received " + results.length);
                                            console.log(JSON.stringify(results, null, 2));
                                            }

                                            , function(error) { // Error
                                            console.log(error);
                                            })

                                            /////

                                            },
                                            function(error) { // Error
                                            console.log(error);
                                            });

                                            <div id="console" />





                                            I have extensively discussed this solution here.






                                            share|improve this answer














                                            The following example I have written shows how to




                                            • Handle asynchronous HTTP calls;

                                            • Wait for response from each API call;

                                            • Use Promise pattern;

                                            • Use Promise.all pattern to join multiple HTTP calls;


                                            This working example is self-contained. It will define a simple request object that uses the window XMLHttpRequest object to make calls. It will define a simple function to wait for a bunch of promises to be completed.



                                            Context. The example is querying the Spotify Web API endpoint in order to search for playlist objects for a given set of query strings:



                                            [
                                            "search?type=playlist&q=%22doom%20metal%22",
                                            "search?type=playlist&q=Adele"
                                            ]


                                            For each item, a new Promise will fire a block - ExecutionBlock, parse the result, schedule a new set of promises based on the result array, that is a list of Spotify user objects and execute the new HTTP call within the ExecutionProfileBlock asynchronously.



                                            You can then see a nested Promise structure, that lets you spawn multiple and completely asynchronous nested HTTP calls, and join the results from each subset of calls through Promise.all.



                                            NOTE
                                            Recent Spotify search APIs will require an access token to be specified in the request headers:



                                            -H "Authorization: Bearer {your access token}" 


                                            So, you to run the following example you need to put your access token in the request headers:






                                            var spotifyAccessToken = "YourSpotifyAccessToken";
                                            var console = {
                                            log: function(s) {
                                            document.getElementById("console").innerHTML += s + "<br/>"
                                            }
                                            }

                                            // Simple XMLHttpRequest
                                            // based on https://davidwalsh.name/xmlhttprequest
                                            SimpleRequest = {
                                            call: function(what, response) {
                                            var request;
                                            if (window.XMLHttpRequest) { // Mozilla, Safari, ...
                                            request = new XMLHttpRequest();
                                            } else if (window.ActiveXObject) { // Internet Explorer
                                            try {
                                            request = new ActiveXObject('Msxml2.XMLHTTP');
                                            }
                                            catch (e) {
                                            try {
                                            request = new ActiveXObject('Microsoft.XMLHTTP');
                                            } catch (e) {}
                                            }
                                            }

                                            // State changes
                                            request.onreadystatechange = function() {
                                            if (request.readyState === 4) { // Done
                                            if (request.status === 200) { // Complete
                                            response(request.responseText)
                                            }
                                            else
                                            response();
                                            }
                                            }
                                            request.open('GET', what, true);
                                            request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
                                            request.send(null);
                                            }
                                            }

                                            //PromiseAll
                                            var promiseAll = function(items, block, done, fail) {
                                            var self = this;
                                            var promises = ,
                                            index = 0;
                                            items.forEach(function(item) {
                                            promises.push(function(item, i) {
                                            return new Promise(function(resolve, reject) {
                                            if (block) {
                                            block.apply(this, [item, index, resolve, reject]);
                                            }
                                            });
                                            }(item, ++index))
                                            });
                                            Promise.all(promises).then(function AcceptHandler(results) {
                                            if (done) done(results);
                                            }, function ErrorHandler(error) {
                                            if (fail) fail(error);
                                            });
                                            }; //promiseAll

                                            // LP: deferred execution block
                                            var ExecutionBlock = function(item, index, resolve, reject) {
                                            var url = "https://api.spotify.com/v1/"
                                            url += item;
                                            console.log( url )
                                            SimpleRequest.call(url, function(result) {
                                            if (result) {

                                            var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
                                            return item.owner.href;
                                            })
                                            resolve(profileUrls);
                                            }
                                            else {
                                            reject(new Error("call error"));
                                            }
                                            })
                                            }

                                            arr = [
                                            "search?type=playlist&q=%22doom%20metal%22",
                                            "search?type=playlist&q=Adele"
                                            ]

                                            promiseAll(arr, function(item, index, resolve, reject) {
                                            console.log("Making request [" + index + "]")
                                            ExecutionBlock(item, index, resolve, reject);
                                            }, function(results) { // Aggregated results

                                            console.log("All profiles received " + results.length);
                                            //console.log(JSON.stringify(results[0], null, 2));

                                            ///// promiseall again

                                            var ExecutionProfileBlock = function(item, index, resolve, reject) {
                                            SimpleRequest.call(item, function(result) {
                                            if (result) {
                                            var obj = JSON.parse(result);
                                            resolve({
                                            name: obj.display_name,
                                            followers: obj.followers.total,
                                            url: obj.href
                                            });
                                            } //result
                                            })
                                            } //ExecutionProfileBlock

                                            promiseAll(results[0], function(item, index, resolve, reject) {
                                            //console.log("Making request [" + index + "] " + item)
                                            ExecutionProfileBlock(item, index, resolve, reject);
                                            }, function(results) { // aggregated results
                                            console.log("All response received " + results.length);
                                            console.log(JSON.stringify(results, null, 2));
                                            }

                                            , function(error) { // Error
                                            console.log(error);
                                            })

                                            /////

                                            },
                                            function(error) { // Error
                                            console.log(error);
                                            });

                                            <div id="console" />





                                            I have extensively discussed this solution here.






                                            var spotifyAccessToken = "YourSpotifyAccessToken";
                                            var console = {
                                            log: function(s) {
                                            document.getElementById("console").innerHTML += s + "<br/>"
                                            }
                                            }

                                            // Simple XMLHttpRequest
                                            // based on https://davidwalsh.name/xmlhttprequest
                                            SimpleRequest = {
                                            call: function(what, response) {
                                            var request;
                                            if (window.XMLHttpRequest) { // Mozilla, Safari, ...
                                            request = new XMLHttpRequest();
                                            } else if (window.ActiveXObject) { // Internet Explorer
                                            try {
                                            request = new ActiveXObject('Msxml2.XMLHTTP');
                                            }
                                            catch (e) {
                                            try {
                                            request = new ActiveXObject('Microsoft.XMLHTTP');
                                            } catch (e) {}
                                            }
                                            }

                                            // State changes
                                            request.onreadystatechange = function() {
                                            if (request.readyState === 4) { // Done
                                            if (request.status === 200) { // Complete
                                            response(request.responseText)
                                            }
                                            else
                                            response();
                                            }
                                            }
                                            request.open('GET', what, true);
                                            request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
                                            request.send(null);
                                            }
                                            }

                                            //PromiseAll
                                            var promiseAll = function(items, block, done, fail) {
                                            var self = this;
                                            var promises = ,
                                            index = 0;
                                            items.forEach(function(item) {
                                            promises.push(function(item, i) {
                                            return new Promise(function(resolve, reject) {
                                            if (block) {
                                            block.apply(this, [item, index, resolve, reject]);
                                            }
                                            });
                                            }(item, ++index))
                                            });
                                            Promise.all(promises).then(function AcceptHandler(results) {
                                            if (done) done(results);
                                            }, function ErrorHandler(error) {
                                            if (fail) fail(error);
                                            });
                                            }; //promiseAll

                                            // LP: deferred execution block
                                            var ExecutionBlock = function(item, index, resolve, reject) {
                                            var url = "https://api.spotify.com/v1/"
                                            url += item;
                                            console.log( url )
                                            SimpleRequest.call(url, function(result) {
                                            if (result) {

                                            var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
                                            return item.owner.href;
                                            })
                                            resolve(profileUrls);
                                            }
                                            else {
                                            reject(new Error("call error"));
                                            }
                                            })
                                            }

                                            arr = [
                                            "search?type=playlist&q=%22doom%20metal%22",
                                            "search?type=playlist&q=Adele"
                                            ]

                                            promiseAll(arr, function(item, index, resolve, reject) {
                                            console.log("Making request [" + index + "]")
                                            ExecutionBlock(item, index, resolve, reject);
                                            }, function(results) { // Aggregated results

                                            console.log("All profiles received " + results.length);
                                            //console.log(JSON.stringify(results[0], null, 2));

                                            ///// promiseall again

                                            var ExecutionProfileBlock = function(item, index, resolve, reject) {
                                            SimpleRequest.call(item, function(result) {
                                            if (result) {
                                            var obj = JSON.parse(result);
                                            resolve({
                                            name: obj.display_name,
                                            followers: obj.followers.total,
                                            url: obj.href
                                            });
                                            } //result
                                            })
                                            } //ExecutionProfileBlock

                                            promiseAll(results[0], function(item, index, resolve, reject) {
                                            //console.log("Making request [" + index + "] " + item)
                                            ExecutionProfileBlock(item, index, resolve, reject);
                                            }, function(results) { // aggregated results
                                            console.log("All response received " + results.length);
                                            console.log(JSON.stringify(results, null, 2));
                                            }

                                            , function(error) { // Error
                                            console.log(error);
                                            })

                                            /////

                                            },
                                            function(error) { // Error
                                            console.log(error);
                                            });

                                            <div id="console" />





                                            var spotifyAccessToken = "YourSpotifyAccessToken";
                                            var console = {
                                            log: function(s) {
                                            document.getElementById("console").innerHTML += s + "<br/>"
                                            }
                                            }

                                            // Simple XMLHttpRequest
                                            // based on https://davidwalsh.name/xmlhttprequest
                                            SimpleRequest = {
                                            call: function(what, response) {
                                            var request;
                                            if (window.XMLHttpRequest) { // Mozilla, Safari, ...
                                            request = new XMLHttpRequest();
                                            } else if (window.ActiveXObject) { // Internet Explorer
                                            try {
                                            request = new ActiveXObject('Msxml2.XMLHTTP');
                                            }
                                            catch (e) {
                                            try {
                                            request = new ActiveXObject('Microsoft.XMLHTTP');
                                            } catch (e) {}
                                            }
                                            }

                                            // State changes
                                            request.onreadystatechange = function() {
                                            if (request.readyState === 4) { // Done
                                            if (request.status === 200) { // Complete
                                            response(request.responseText)
                                            }
                                            else
                                            response();
                                            }
                                            }
                                            request.open('GET', what, true);
                                            request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
                                            request.send(null);
                                            }
                                            }

                                            //PromiseAll
                                            var promiseAll = function(items, block, done, fail) {
                                            var self = this;
                                            var promises = ,
                                            index = 0;
                                            items.forEach(function(item) {
                                            promises.push(function(item, i) {
                                            return new Promise(function(resolve, reject) {
                                            if (block) {
                                            block.apply(this, [item, index, resolve, reject]);
                                            }
                                            });
                                            }(item, ++index))
                                            });
                                            Promise.all(promises).then(function AcceptHandler(results) {
                                            if (done) done(results);
                                            }, function ErrorHandler(error) {
                                            if (fail) fail(error);
                                            });
                                            }; //promiseAll

                                            // LP: deferred execution block
                                            var ExecutionBlock = function(item, index, resolve, reject) {
                                            var url = "https://api.spotify.com/v1/"
                                            url += item;
                                            console.log( url )
                                            SimpleRequest.call(url, function(result) {
                                            if (result) {

                                            var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
                                            return item.owner.href;
                                            })
                                            resolve(profileUrls);
                                            }
                                            else {
                                            reject(new Error("call error"));
                                            }
                                            })
                                            }

                                            arr = [
                                            "search?type=playlist&q=%22doom%20metal%22",
                                            "search?type=playlist&q=Adele"
                                            ]

                                            promiseAll(arr, function(item, index, resolve, reject) {
                                            console.log("Making request [" + index + "]")
                                            ExecutionBlock(item, index, resolve, reject);
                                            }, function(results) { // Aggregated results

                                            console.log("All profiles received " + results.length);
                                            //console.log(JSON.stringify(results[0], null, 2));

                                            ///// promiseall again

                                            var ExecutionProfileBlock = function(item, index, resolve, reject) {
                                            SimpleRequest.call(item, function(result) {
                                            if (result) {
                                            var obj = JSON.parse(result);
                                            resolve({
                                            name: obj.display_name,
                                            followers: obj.followers.total,
                                            url: obj.href
                                            });
                                            } //result
                                            })
                                            } //ExecutionProfileBlock

                                            promiseAll(results[0], function(item, index, resolve, reject) {
                                            //console.log("Making request [" + index + "] " + item)
                                            ExecutionProfileBlock(item, index, resolve, reject);
                                            }, function(results) { // aggregated results
                                            console.log("All response received " + results.length);
                                            console.log(JSON.stringify(results, null, 2));
                                            }

                                            , function(error) { // Error
                                            console.log(error);
                                            })

                                            /////

                                            },
                                            function(error) { // Error
                                            console.log(error);
                                            });

                                            <div id="console" />






                                            share|improve this answer














                                            share|improve this answer



                                            share|improve this answer








                                            edited Nov 28 at 16:42

























                                            answered Apr 12 '16 at 22:55









                                            loretoparisi

                                            7,57754771




                                            7,57754771






















                                                up vote
                                                55
                                                down vote













                                                2017 answer: you can now do exactly what you want in every current browser and node



                                                This is quite simple:




                                                • Return a Promise

                                                • Use the 'await', which will tell JavaScript to await the promise to be resolved into a value (like the HTTP response)

                                                • Add the 'async' keyword to the parent function


                                                Here's a working version of your code:



                                                (async function(){

                                                var response = await superagent.get('...')
                                                console.log(response)

                                                })()


                                                await is supported in all current browsers and node 8






                                                share|improve this answer



















                                                • 6




                                                  Unfortunately, this works only with functions that return promises – for example it doesn't work with Node.js API, which uses callbacks. And I wouldn't recommend using it without Babel, because not everyone uses "current browsers".
                                                  – Michał Perłakowski
                                                  Jun 8 '17 at 6:47






                                                • 1




                                                  @MichałPerłakowski node 8 includes nodejs.org/api/util.html#util_util_promisify_original which can be used to make the node.js API return promises. Whether you have the time and money to support non-current browsers obviously depends on your situation.
                                                  – mikemaccana
                                                  Jun 9 '17 at 18:28












                                                • IE 11 is still a current browser in 2018, sadly and it doesn't support await/async
                                                  – Juan Mendes
                                                  Oct 4 at 14:51










                                                • IE11 is not a current browser. It was released 5 years ago, has a worldwide market share of 2.5% according to caniuse, and unless someone is doubling your budget to ignore all current tech then it's not worth most people's time.
                                                  – mikemaccana
                                                  Oct 4 at 14:57















                                                up vote
                                                55
                                                down vote













                                                2017 answer: you can now do exactly what you want in every current browser and node



                                                This is quite simple:




                                                • Return a Promise

                                                • Use the 'await', which will tell JavaScript to await the promise to be resolved into a value (like the HTTP response)

                                                • Add the 'async' keyword to the parent function


                                                Here's a working version of your code:



                                                (async function(){

                                                var response = await superagent.get('...')
                                                console.log(response)

                                                })()


                                                await is supported in all current browsers and node 8






                                                share|improve this answer



















                                                • 6




                                                  Unfortunately, this works only with functions that return promises – for example it doesn't work with Node.js API, which uses callbacks. And I wouldn't recommend using it without Babel, because not everyone uses "current browsers".
                                                  – Michał Perłakowski
                                                  Jun 8 '17 at 6:47






                                                • 1




                                                  @MichałPerłakowski node 8 includes nodejs.org/api/util.html#util_util_promisify_original which can be used to make the node.js API return promises. Whether you have the time and money to support non-current browsers obviously depends on your situation.
                                                  – mikemaccana
                                                  Jun 9 '17 at 18:28












                                                • IE 11 is still a current browser in 2018, sadly and it doesn't support await/async
                                                  – Juan Mendes
                                                  Oct 4 at 14:51










                                                • IE11 is not a current browser. It was released 5 years ago, has a worldwide market share of 2.5% according to caniuse, and unless someone is doubling your budget to ignore all current tech then it's not worth most people's time.
                                                  – mikemaccana
                                                  Oct 4 at 14:57













                                                up vote
                                                55
                                                down vote










                                                up vote
                                                55
                                                down vote









                                                2017 answer: you can now do exactly what you want in every current browser and node



                                                This is quite simple:




                                                • Return a Promise

                                                • Use the 'await', which will tell JavaScript to await the promise to be resolved into a value (like the HTTP response)

                                                • Add the 'async' keyword to the parent function


                                                Here's a working version of your code:



                                                (async function(){

                                                var response = await superagent.get('...')
                                                console.log(response)

                                                })()


                                                await is supported in all current browsers and node 8






                                                share|improve this answer














                                                2017 answer: you can now do exactly what you want in every current browser and node



                                                This is quite simple:




                                                • Return a Promise

                                                • Use the 'await', which will tell JavaScript to await the promise to be resolved into a value (like the HTTP response)

                                                • Add the 'async' keyword to the parent function


                                                Here's a working version of your code:



                                                (async function(){

                                                var response = await superagent.get('...')
                                                console.log(response)

                                                })()


                                                await is supported in all current browsers and node 8







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Oct 1 at 10:06

























                                                answered Jun 2 '17 at 9:51









                                                mikemaccana

                                                41.5k44228292




                                                41.5k44228292








                                                • 6




                                                  Unfortunately, this works only with functions that return promises – for example it doesn't work with Node.js API, which uses callbacks. And I wouldn't recommend using it without Babel, because not everyone uses "current browsers".
                                                  – Michał Perłakowski
                                                  Jun 8 '17 at 6:47






                                                • 1




                                                  @MichałPerłakowski node 8 includes nodejs.org/api/util.html#util_util_promisify_original which can be used to make the node.js API return promises. Whether you have the time and money to support non-current browsers obviously depends on your situation.
                                                  – mikemaccana
                                                  Jun 9 '17 at 18:28












                                                • IE 11 is still a current browser in 2018, sadly and it doesn't support await/async
                                                  – Juan Mendes
                                                  Oct 4 at 14:51










                                                • IE11 is not a current browser. It was released 5 years ago, has a worldwide market share of 2.5% according to caniuse, and unless someone is doubling your budget to ignore all current tech then it's not worth most people's time.
                                                  – mikemaccana
                                                  Oct 4 at 14:57














                                                • 6




                                                  Unfortunately, this works only with functions that return promises – for example it doesn't work with Node.js API, which uses callbacks. And I wouldn't recommend using it without Babel, because not everyone uses "current browsers".
                                                  – Michał Perłakowski
                                                  Jun 8 '17 at 6:47






                                                • 1




                                                  @MichałPerłakowski node 8 includes nodejs.org/api/util.html#util_util_promisify_original which can be used to make the node.js API return promises. Whether you have the time and money to support non-current browsers obviously depends on your situation.
                                                  – mikemaccana
                                                  Jun 9 '17 at 18:28












                                                • IE 11 is still a current browser in 2018, sadly and it doesn't support await/async
                                                  – Juan Mendes
                                                  Oct 4 at 14:51










                                                • IE11 is not a current browser. It was released 5 years ago, has a worldwide market share of 2.5% according to caniuse, and unless someone is doubling your budget to ignore all current tech then it's not worth most people's time.
                                                  – mikemaccana
                                                  Oct 4 at 14:57








                                                6




                                                6




                                                Unfortunately, this works only with functions that return promises – for example it doesn't work with Node.js API, which uses callbacks. And I wouldn't recommend using it without Babel, because not everyone uses "current browsers".
                                                – Michał Perłakowski
                                                Jun 8 '17 at 6:47




                                                Unfortunately, this works only with functions that return promises – for example it doesn't work with Node.js API, which uses callbacks. And I wouldn't recommend using it without Babel, because not everyone uses "current browsers".
                                                – Michał Perłakowski
                                                Jun 8 '17 at 6:47




                                                1




                                                1




                                                @MichałPerłakowski node 8 includes nodejs.org/api/util.html#util_util_promisify_original which can be used to make the node.js API return promises. Whether you have the time and money to support non-current browsers obviously depends on your situation.
                                                – mikemaccana
                                                Jun 9 '17 at 18:28






                                                @MichałPerłakowski node 8 includes nodejs.org/api/util.html#util_util_promisify_original which can be used to make the node.js API return promises. Whether you have the time and money to support non-current browsers obviously depends on your situation.
                                                – mikemaccana
                                                Jun 9 '17 at 18:28














                                                IE 11 is still a current browser in 2018, sadly and it doesn't support await/async
                                                – Juan Mendes
                                                Oct 4 at 14:51




                                                IE 11 is still a current browser in 2018, sadly and it doesn't support await/async
                                                – Juan Mendes
                                                Oct 4 at 14:51












                                                IE11 is not a current browser. It was released 5 years ago, has a worldwide market share of 2.5% according to caniuse, and unless someone is doubling your budget to ignore all current tech then it's not worth most people's time.
                                                – mikemaccana
                                                Oct 4 at 14:57




                                                IE11 is not a current browser. It was released 5 years ago, has a worldwide market share of 2.5% according to caniuse, and unless someone is doubling your budget to ignore all current tech then it's not worth most people's time.
                                                – mikemaccana
                                                Oct 4 at 14:57










                                                up vote
                                                50
                                                down vote













                                                You can use this custom library (written using Promise) to make a remote call.



                                                function $http(apiConfig) {
                                                return new Promise(function (resolve, reject) {
                                                var client = new XMLHttpRequest();
                                                client.open(apiConfig.method, apiConfig.url);
                                                client.send();
                                                client.onload = function () {
                                                if (this.status >= 200 && this.status < 300) {
                                                // Performs the function "resolve" when this.status is equal to 2xx.
                                                // Your logic here.
                                                resolve(this.response);
                                                }
                                                else {
                                                // Performs the function "reject" when this.status is different than 2xx.
                                                reject(this.statusText);
                                                }
                                                };
                                                client.onerror = function () {
                                                reject(this.statusText);
                                                };
                                                });
                                                }


                                                Simple usage example:



                                                $http({
                                                method: 'get',
                                                url: 'google.com'
                                                }).then(function(response) {
                                                console.log(response);
                                                }, function(error) {
                                                console.log(error)
                                                });





                                                share|improve this answer



























                                                  up vote
                                                  50
                                                  down vote













                                                  You can use this custom library (written using Promise) to make a remote call.



                                                  function $http(apiConfig) {
                                                  return new Promise(function (resolve, reject) {
                                                  var client = new XMLHttpRequest();
                                                  client.open(apiConfig.method, apiConfig.url);
                                                  client.send();
                                                  client.onload = function () {
                                                  if (this.status >= 200 && this.status < 300) {
                                                  // Performs the function "resolve" when this.status is equal to 2xx.
                                                  // Your logic here.
                                                  resolve(this.response);
                                                  }
                                                  else {
                                                  // Performs the function "reject" when this.status is different than 2xx.
                                                  reject(this.statusText);
                                                  }
                                                  };
                                                  client.onerror = function () {
                                                  reject(this.statusText);
                                                  };
                                                  });
                                                  }


                                                  Simple usage example:



                                                  $http({
                                                  method: 'get',
                                                  url: 'google.com'
                                                  }).then(function(response) {
                                                  console.log(response);
                                                  }, function(error) {
                                                  console.log(error)
                                                  });





                                                  share|improve this answer

























                                                    up vote
                                                    50
                                                    down vote










                                                    up vote
                                                    50
                                                    down vote









                                                    You can use this custom library (written using Promise) to make a remote call.



                                                    function $http(apiConfig) {
                                                    return new Promise(function (resolve, reject) {
                                                    var client = new XMLHttpRequest();
                                                    client.open(apiConfig.method, apiConfig.url);
                                                    client.send();
                                                    client.onload = function () {
                                                    if (this.status >= 200 && this.status < 300) {
                                                    // Performs the function "resolve" when this.status is equal to 2xx.
                                                    // Your logic here.
                                                    resolve(this.response);
                                                    }
                                                    else {
                                                    // Performs the function "reject" when this.status is different than 2xx.
                                                    reject(this.statusText);
                                                    }
                                                    };
                                                    client.onerror = function () {
                                                    reject(this.statusText);
                                                    };
                                                    });
                                                    }


                                                    Simple usage example:



                                                    $http({
                                                    method: 'get',
                                                    url: 'google.com'
                                                    }).then(function(response) {
                                                    console.log(response);
                                                    }, function(error) {
                                                    console.log(error)
                                                    });





                                                    share|improve this answer














                                                    You can use this custom library (written using Promise) to make a remote call.



                                                    function $http(apiConfig) {
                                                    return new Promise(function (resolve, reject) {
                                                    var client = new XMLHttpRequest();
                                                    client.open(apiConfig.method, apiConfig.url);
                                                    client.send();
                                                    client.onload = function () {
                                                    if (this.status >= 200 && this.status < 300) {
                                                    // Performs the function "resolve" when this.status is equal to 2xx.
                                                    // Your logic here.
                                                    resolve(this.response);
                                                    }
                                                    else {
                                                    // Performs the function "reject" when this.status is different than 2xx.
                                                    reject(this.statusText);
                                                    }
                                                    };
                                                    client.onerror = function () {
                                                    reject(this.statusText);
                                                    };
                                                    });
                                                    }


                                                    Simple usage example:



                                                    $http({
                                                    method: 'get',
                                                    url: 'google.com'
                                                    }).then(function(response) {
                                                    console.log(response);
                                                    }, function(error) {
                                                    console.log(error)
                                                    });






                                                    share|improve this answer














                                                    share|improve this answer



                                                    share|improve this answer








                                                    edited Dec 17 '16 at 10:59









                                                    Peter Mortensen

                                                    13.4k1983111




                                                    13.4k1983111










                                                    answered May 26 '16 at 13:26









                                                    Vinoth Rajendran

                                                    7121722




                                                    7121722






















                                                        up vote
                                                        47
                                                        down vote














                                                        Js is a single threaded.




                                                        Browser can be divided into three parts:



                                                        1)Event Loop



                                                        2)Web API



                                                        3)Event Queue



                                                        Event Loop runs for forever i.e kind of infinite loop.Event Queue is where all your function are pushed on some event(example:click) this is one by one carried out of queue and put into Event loop which execute this function and prepares it self for next one after first one is executed.This means Execution of one function doesn't starts till the function before it in queue is executed in event loop.



                                                        Now let us think we pushed two functions in a queue one is for getting a data from server and another utilises that data.We pushed the serverRequest() function in queue first then utiliseData() function. serverRequest function goes in event loop and makes a call to server as we never know how much time it will take to get data from server
                                                        so this process is expected to take time and so we busy our event loop thus hanging our page, that's where Web API come into role it take this function from event loop and deals with server making event loop free so that we can execute next function from queue.The next function in queue is utiliseData() which goes in loop but because of no data available it goes waste and execution of next function continues till end of the queue.(This is called Async calling i.e we can do something else till we get data)



                                                        Let suppose our serverRequest() function had a return statement in a code, when we get back data from server Web API will push it in queue at the end of queue.
                                                        As it get pushed at end in queue we cannot utilise its data as there is no function left in our queue to utilise this data.Thus it is not possible to return something from Async Call.



                                                        Thus Solution to this is callback or promise.



                                                        A Image from one of the answers here, Correctly explains callback use...
                                                        We give our function(function utilising data returned from server) to function calling server.



                                                        CallBack



                                                         function doAjax(callbackFunc, method, url) {
                                                        var xmlHttpReq = new XMLHttpRequest();
                                                        xmlHttpReq.open(method, url);
                                                        xmlHttpReq.onreadystatechange = function() {

                                                        if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
                                                        callbackFunc(xmlHttpReq.responseText);
                                                        }


                                                        }
                                                        xmlHttpReq.send(null);

                                                        }


                                                        In my Code it is called as



                                                        function loadMyJson(categoryValue){
                                                        if(categoryValue==="veg")
                                                        doAjax(print,"GET","http://localhost:3004/vegetables");
                                                        else if(categoryValue==="fruits")
                                                        doAjax(print,"GET","http://localhost:3004/fruits");
                                                        else
                                                        console.log("Data not found");
                                                        }


                                                        Read here for new methods in ECMA(2016/17) for making async call(@Felix Kling Answer on Top)
                                                        https://stackoverflow.com/a/14220323/7579856






                                                        share|improve this answer























                                                        • for nice picture +1
                                                          – Kamil Kiełczewski
                                                          Dec 3 at 18:12















                                                        up vote
                                                        47
                                                        down vote














                                                        Js is a single threaded.




                                                        Browser can be divided into three parts:



                                                        1)Event Loop



                                                        2)Web API



                                                        3)Event Queue



                                                        Event Loop runs for forever i.e kind of infinite loop.Event Queue is where all your function are pushed on some event(example:click) this is one by one carried out of queue and put into Event loop which execute this function and prepares it self for next one after first one is executed.This means Execution of one function doesn't starts till the function before it in queue is executed in event loop.



                                                        Now let us think we pushed two functions in a queue one is for getting a data from server and another utilises that data.We pushed the serverRequest() function in queue first then utiliseData() function. serverRequest function goes in event loop and makes a call to server as we never know how much time it will take to get data from server
                                                        so this process is expected to take time and so we busy our event loop thus hanging our page, that's where Web API come into role it take this function from event loop and deals with server making event loop free so that we can execute next function from queue.The next function in queue is utiliseData() which goes in loop but because of no data available it goes waste and execution of next function continues till end of the queue.(This is called Async calling i.e we can do something else till we get data)



                                                        Let suppose our serverRequest() function had a return statement in a code, when we get back data from server Web API will push it in queue at the end of queue.
                                                        As it get pushed at end in queue we cannot utilise its data as there is no function left in our queue to utilise this data.Thus it is not possible to return something from Async Call.



                                                        Thus Solution to this is callback or promise.



                                                        A Image from one of the answers here, Correctly explains callback use...
                                                        We give our function(function utilising data returned from server) to function calling server.



                                                        CallBack



                                                         function doAjax(callbackFunc, method, url) {
                                                        var xmlHttpReq = new XMLHttpRequest();
                                                        xmlHttpReq.open(method, url);
                                                        xmlHttpReq.onreadystatechange = function() {

                                                        if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
                                                        callbackFunc(xmlHttpReq.responseText);
                                                        }


                                                        }
                                                        xmlHttpReq.send(null);

                                                        }


                                                        In my Code it is called as



                                                        function loadMyJson(categoryValue){
                                                        if(categoryValue==="veg")
                                                        doAjax(print,"GET","http://localhost:3004/vegetables");
                                                        else if(categoryValue==="fruits")
                                                        doAjax(print,"GET","http://localhost:3004/fruits");
                                                        else
                                                        console.log("Data not found");
                                                        }


                                                        Read here for new methods in ECMA(2016/17) for making async call(@Felix Kling Answer on Top)
                                                        https://stackoverflow.com/a/14220323/7579856






                                                        share|improve this answer























                                                        • for nice picture +1
                                                          – Kamil Kiełczewski
                                                          Dec 3 at 18:12













                                                        up vote
                                                        47
                                                        down vote










                                                        up vote
                                                        47
                                                        down vote










                                                        Js is a single threaded.




                                                        Browser can be divided into three parts:



                                                        1)Event Loop



                                                        2)Web API



                                                        3)Event Queue



                                                        Event Loop runs for forever i.e kind of infinite loop.Event Queue is where all your function are pushed on some event(example:click) this is one by one carried out of queue and put into Event loop which execute this function and prepares it self for next one after first one is executed.This means Execution of one function doesn't starts till the function before it in queue is executed in event loop.



                                                        Now let us think we pushed two functions in a queue one is for getting a data from server and another utilises that data.We pushed the serverRequest() function in queue first then utiliseData() function. serverRequest function goes in event loop and makes a call to server as we never know how much time it will take to get data from server
                                                        so this process is expected to take time and so we busy our event loop thus hanging our page, that's where Web API come into role it take this function from event loop and deals with server making event loop free so that we can execute next function from queue.The next function in queue is utiliseData() which goes in loop but because of no data available it goes waste and execution of next function continues till end of the queue.(This is called Async calling i.e we can do something else till we get data)



                                                        Let suppose our serverRequest() function had a return statement in a code, when we get back data from server Web API will push it in queue at the end of queue.
                                                        As it get pushed at end in queue we cannot utilise its data as there is no function left in our queue to utilise this data.Thus it is not possible to return something from Async Call.



                                                        Thus Solution to this is callback or promise.



                                                        A Image from one of the answers here, Correctly explains callback use...
                                                        We give our function(function utilising data returned from server) to function calling server.



                                                        CallBack



                                                         function doAjax(callbackFunc, method, url) {
                                                        var xmlHttpReq = new XMLHttpRequest();
                                                        xmlHttpReq.open(method, url);
                                                        xmlHttpReq.onreadystatechange = function() {

                                                        if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
                                                        callbackFunc(xmlHttpReq.responseText);
                                                        }


                                                        }
                                                        xmlHttpReq.send(null);

                                                        }


                                                        In my Code it is called as



                                                        function loadMyJson(categoryValue){
                                                        if(categoryValue==="veg")
                                                        doAjax(print,"GET","http://localhost:3004/vegetables");
                                                        else if(categoryValue==="fruits")
                                                        doAjax(print,"GET","http://localhost:3004/fruits");
                                                        else
                                                        console.log("Data not found");
                                                        }


                                                        Read here for new methods in ECMA(2016/17) for making async call(@Felix Kling Answer on Top)
                                                        https://stackoverflow.com/a/14220323/7579856






                                                        share|improve this answer















                                                        Js is a single threaded.




                                                        Browser can be divided into three parts:



                                                        1)Event Loop



                                                        2)Web API



                                                        3)Event Queue



                                                        Event Loop runs for forever i.e kind of infinite loop.Event Queue is where all your function are pushed on some event(example:click) this is one by one carried out of queue and put into Event loop which execute this function and prepares it self for next one after first one is executed.This means Execution of one function doesn't starts till the function before it in queue is executed in event loop.



                                                        Now let us think we pushed two functions in a queue one is for getting a data from server and another utilises that data.We pushed the serverRequest() function in queue first then utiliseData() function. serverRequest function goes in event loop and makes a call to server as we never know how much time it will take to get data from server
                                                        so this process is expected to take time and so we busy our event loop thus hanging our page, that's where Web API come into role it take this function from event loop and deals with server making event loop free so that we can execute next function from queue.The next function in queue is utiliseData() which goes in loop but because of no data available it goes waste and execution of next function continues till end of the queue.(This is called Async calling i.e we can do something else till we get data)



                                                        Let suppose our serverRequest() function had a return statement in a code, when we get back data from server Web API will push it in queue at the end of queue.
                                                        As it get pushed at end in queue we cannot utilise its data as there is no function left in our queue to utilise this data.Thus it is not possible to return something from Async Call.



                                                        Thus Solution to this is callback or promise.



                                                        A Image from one of the answers here, Correctly explains callback use...
                                                        We give our function(function utilising data returned from server) to function calling server.



                                                        CallBack



                                                         function doAjax(callbackFunc, method, url) {
                                                        var xmlHttpReq = new XMLHttpRequest();
                                                        xmlHttpReq.open(method, url);
                                                        xmlHttpReq.onreadystatechange = function() {

                                                        if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
                                                        callbackFunc(xmlHttpReq.responseText);
                                                        }


                                                        }
                                                        xmlHttpReq.send(null);

                                                        }


                                                        In my Code it is called as



                                                        function loadMyJson(categoryValue){
                                                        if(categoryValue==="veg")
                                                        doAjax(print,"GET","http://localhost:3004/vegetables");
                                                        else if(categoryValue==="fruits")
                                                        doAjax(print,"GET","http://localhost:3004/fruits");
                                                        else
                                                        console.log("Data not found");
                                                        }


                                                        Read here for new methods in ECMA(2016/17) for making async call(@Felix Kling Answer on Top)
                                                        https://stackoverflow.com/a/14220323/7579856







                                                        share|improve this answer














                                                        share|improve this answer



                                                        share|improve this answer








                                                        edited Mar 16 at 16:48

























                                                        answered Feb 3 at 6:06









                                                        Aniket Jha

                                                        85559




                                                        85559












                                                        • for nice picture +1
                                                          – Kamil Kiełczewski
                                                          Dec 3 at 18:12


















                                                        • for nice picture +1
                                                          – Kamil Kiełczewski
                                                          Dec 3 at 18:12
















                                                        for nice picture +1
                                                        – Kamil Kiełczewski
                                                        Dec 3 at 18:12




                                                        for nice picture +1
                                                        – Kamil Kiełczewski
                                                        Dec 3 at 18:12










                                                        up vote
                                                        45
                                                        down vote













                                                        Another solution is to execute code via sequential executor nsynjs.



                                                        If underlying function is promisified



                                                        nsynjs will evaluate all promises sequentially, and put promise result into data property:






                                                        function synchronousCode() {

                                                        var getURL = function(url) {
                                                        return window.fetch(url).data.text().data;
                                                        };

                                                        var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
                                                        console.log('received bytes:',getURL(url).length);

                                                        };

                                                        nsynjs.run(synchronousCode,{},function(){
                                                        console.log('synchronousCode done');
                                                        });

                                                        <script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>





                                                        If underlying function is not promisified



                                                        Step 1. Wrap function with callback into nsynjs-aware wrapper (if it has promisified version, you can skip this test):



                                                        var ajaxGet = function (ctx,url) {
                                                        var res = {};
                                                        var ex;
                                                        $.ajax(url)
                                                        .done(function (data) {
                                                        res.data = data;
                                                        })
                                                        .fail(function(e) {
                                                        ex = e;
                                                        })
                                                        .always(function() {
                                                        ctx.resume(ex);
                                                        });
                                                        return res;
                                                        };
                                                        ajaxGet.nsynjsHasCallback = true;


                                                        Step 2. Put synchronous logic into function:



                                                        function process() {
                                                        console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
                                                        }


                                                        Step 3. Run function in synchronous manner via nnsynjs:



                                                        nsynjs.run(process,this,function () {
                                                        console.log("synchronous function finished");
                                                        });


                                                        Nsynjs will evaluate all operators and expressions step-by-step, pausing execution in case if result of some slow function is not ready.



                                                        More examples here: https://github.com/amaksr/nsynjs/tree/master/examples






                                                        share|improve this answer



















                                                        • 1




                                                          This is interesting. I like how it allows to code async calls the way you'd do it in other languages. But technically it's not real JavaScript?
                                                          – J Morris
                                                          Jun 16 '17 at 23:55















                                                        up vote
                                                        45
                                                        down vote













                                                        Another solution is to execute code via sequential executor nsynjs.



                                                        If underlying function is promisified



                                                        nsynjs will evaluate all promises sequentially, and put promise result into data property:






                                                        function synchronousCode() {

                                                        var getURL = function(url) {
                                                        return window.fetch(url).data.text().data;
                                                        };

                                                        var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
                                                        console.log('received bytes:',getURL(url).length);

                                                        };

                                                        nsynjs.run(synchronousCode,{},function(){
                                                        console.log('synchronousCode done');
                                                        });

                                                        <script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>





                                                        If underlying function is not promisified



                                                        Step 1. Wrap function with callback into nsynjs-aware wrapper (if it has promisified version, you can skip this test):



                                                        var ajaxGet = function (ctx,url) {
                                                        var res = {};
                                                        var ex;
                                                        $.ajax(url)
                                                        .done(function (data) {
                                                        res.data = data;
                                                        })
                                                        .fail(function(e) {
                                                        ex = e;
                                                        })
                                                        .always(function() {
                                                        ctx.resume(ex);
                                                        });
                                                        return res;
                                                        };
                                                        ajaxGet.nsynjsHasCallback = true;


                                                        Step 2. Put synchronous logic into function:



                                                        function process() {
                                                        console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
                                                        }


                                                        Step 3. Run function in synchronous manner via nnsynjs:



                                                        nsynjs.run(process,this,function () {
                                                        console.log("synchronous function finished");
                                                        });


                                                        Nsynjs will evaluate all operators and expressions step-by-step, pausing execution in case if result of some slow function is not ready.



                                                        More examples here: https://github.com/amaksr/nsynjs/tree/master/examples






                                                        share|improve this answer



















                                                        • 1




                                                          This is interesting. I like how it allows to code async calls the way you'd do it in other languages. But technically it's not real JavaScript?
                                                          – J Morris
                                                          Jun 16 '17 at 23:55













                                                        up vote
                                                        45
                                                        down vote










                                                        up vote
                                                        45
                                                        down vote









                                                        Another solution is to execute code via sequential executor nsynjs.



                                                        If underlying function is promisified



                                                        nsynjs will evaluate all promises sequentially, and put promise result into data property:






                                                        function synchronousCode() {

                                                        var getURL = function(url) {
                                                        return window.fetch(url).data.text().data;
                                                        };

                                                        var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
                                                        console.log('received bytes:',getURL(url).length);

                                                        };

                                                        nsynjs.run(synchronousCode,{},function(){
                                                        console.log('synchronousCode done');
                                                        });

                                                        <script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>





                                                        If underlying function is not promisified



                                                        Step 1. Wrap function with callback into nsynjs-aware wrapper (if it has promisified version, you can skip this test):



                                                        var ajaxGet = function (ctx,url) {
                                                        var res = {};
                                                        var ex;
                                                        $.ajax(url)
                                                        .done(function (data) {
                                                        res.data = data;
                                                        })
                                                        .fail(function(e) {
                                                        ex = e;
                                                        })
                                                        .always(function() {
                                                        ctx.resume(ex);
                                                        });
                                                        return res;
                                                        };
                                                        ajaxGet.nsynjsHasCallback = true;


                                                        Step 2. Put synchronous logic into function:



                                                        function process() {
                                                        console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
                                                        }


                                                        Step 3. Run function in synchronous manner via nnsynjs:



                                                        nsynjs.run(process,this,function () {
                                                        console.log("synchronous function finished");
                                                        });


                                                        Nsynjs will evaluate all operators and expressions step-by-step, pausing execution in case if result of some slow function is not ready.



                                                        More examples here: https://github.com/amaksr/nsynjs/tree/master/examples






                                                        share|improve this answer














                                                        Another solution is to execute code via sequential executor nsynjs.



                                                        If underlying function is promisified



                                                        nsynjs will evaluate all promises sequentially, and put promise result into data property:






                                                        function synchronousCode() {

                                                        var getURL = function(url) {
                                                        return window.fetch(url).data.text().data;
                                                        };

                                                        var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
                                                        console.log('received bytes:',getURL(url).length);

                                                        };

                                                        nsynjs.run(synchronousCode,{},function(){
                                                        console.log('synchronousCode done');
                                                        });

                                                        <script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>





                                                        If underlying function is not promisified



                                                        Step 1. Wrap function with callback into nsynjs-aware wrapper (if it has promisified version, you can skip this test):



                                                        var ajaxGet = function (ctx,url) {
                                                        var res = {};
                                                        var ex;
                                                        $.ajax(url)
                                                        .done(function (data) {
                                                        res.data = data;
                                                        })
                                                        .fail(function(e) {
                                                        ex = e;
                                                        })
                                                        .always(function() {
                                                        ctx.resume(ex);
                                                        });
                                                        return res;
                                                        };
                                                        ajaxGet.nsynjsHasCallback = true;


                                                        Step 2. Put synchronous logic into function:



                                                        function process() {
                                                        console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
                                                        }


                                                        Step 3. Run function in synchronous manner via nnsynjs:



                                                        nsynjs.run(process,this,function () {
                                                        console.log("synchronous function finished");
                                                        });


                                                        Nsynjs will evaluate all operators and expressions step-by-step, pausing execution in case if result of some slow function is not ready.



                                                        More examples here: https://github.com/amaksr/nsynjs/tree/master/examples






                                                        function synchronousCode() {

                                                        var getURL = function(url) {
                                                        return window.fetch(url).data.text().data;
                                                        };

                                                        var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
                                                        console.log('received bytes:',getURL(url).length);

                                                        };

                                                        nsynjs.run(synchronousCode,{},function(){
                                                        console.log('synchronousCode done');
                                                        });

                                                        <script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>





                                                        function synchronousCode() {

                                                        var getURL = function(url) {
                                                        return window.fetch(url).data.text().data;
                                                        };

                                                        var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
                                                        console.log('received bytes:',getURL(url).length);

                                                        };

                                                        nsynjs.run(synchronousCode,{},function(){
                                                        console.log('synchronousCode done');
                                                        });

                                                        <script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>






                                                        share|improve this answer














                                                        share|improve this answer



                                                        share|improve this answer








                                                        edited Jul 4 '17 at 20:30

























                                                        answered May 27 '17 at 2:47









                                                        amaksr

                                                        5,01921015




                                                        5,01921015








                                                        • 1




                                                          This is interesting. I like how it allows to code async calls the way you'd do it in other languages. But technically it's not real JavaScript?
                                                          – J Morris
                                                          Jun 16 '17 at 23:55














                                                        • 1




                                                          This is interesting. I like how it allows to code async calls the way you'd do it in other languages. But technically it's not real JavaScript?
                                                          – J Morris
                                                          Jun 16 '17 at 23:55








                                                        1




                                                        1




                                                        This is interesting. I like how it allows to code async calls the way you'd do it in other languages. But technically it's not real JavaScript?
                                                        – J Morris
                                                        Jun 16 '17 at 23:55




                                                        This is interesting. I like how it allows to code async calls the way you'd do it in other languages. But technically it's not real JavaScript?
                                                        – J Morris
                                                        Jun 16 '17 at 23:55










                                                        up vote
                                                        35
                                                        down vote













                                                        It's a very common issue we face while struggling with the 'mysteries' of JavaScript. Let me try demystifying this mystery today.



                                                        Let's start with a simple JavaScript function:



                                                        function foo(){
                                                        // do something
                                                        return 'wohoo';
                                                        }

                                                        let bar = foo(); // bar is 'wohoo' here


                                                        That's a simple synchronous function call (where each line of code is 'finished with its job' before the next one in sequence), and the result is same as expected.



                                                        Now let's add a bit of twist, by introducing little delay in our function, so that all lines of code are not 'finished' in sequence. Thus, it will emulate the asynchronous behavior of function :



                                                        function foo(){
                                                        setTimeout( ()=>{
                                                        return 'wohoo';
                                                        }, 1000 )
                                                        }

                                                        let bar = foo() // bar is undefined here


                                                        So there you go, that delay just broke the functionality we expected! But what exactly happened ? Well, it's actually pretty logical if you look at the code. the function foo(), upon execution, returns nothing (thus returned value is undefined), but it does start a timer, which executes a function after 1s to return 'wohoo'. But as you can see, the value that's assigned to bar is the immediately returned stuff from foo(), not anything else that comes later.



                                                        So, how do we tackle this issue?



                                                        Let's ask our function for a PROMISE.
                                                        Promise is really about what it means : it means that the function guarantees you to provide with any output it gets in future. so let's see it in action for our little problem above :



                                                        function foo(){
                                                        return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
                                                        setTimeout ( function(){
                                                        // promise is RESOLVED , when execution reaches this line of code
                                                        resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
                                                        }, 1000 )
                                                        })
                                                        }

                                                        let bar ;
                                                        foo().then( res => {
                                                        bar = res;
                                                        console.log(bar) // will print 'wohoo'
                                                        });


                                                        Thus, the summary is - to tackle the asynchronous functions like ajax based calls etc., you can use a promise to resolve the value (which you intend to return). Thus, in short you resolve value instead of returning, in asynchronous functions.



                                                        UPDATE (Promises with async/await)



                                                        Apart from using then/catch to work with promises, there exists one more approach. The idea is to recognize an asynchronous function and then wait for the promises to resolve, before moving to the next line of code. It's still just the promises under the hood, but with a different syntactical approach. To make things clearer, you can find a comparison below:



                                                        then/catch version:



                                                        function fetchUsers(){
                                                        let users = ;
                                                        getUsers()
                                                        .then(_users => users = _users)
                                                        .catch(err =>{
                                                        throw err
                                                        })
                                                        return users;
                                                        }


                                                        async/await version:



                                                          async function fetchUsers(){
                                                        try{
                                                        let users = await getUsers()
                                                        return users;
                                                        }
                                                        catch(err){
                                                        throw err;
                                                        }
                                                        }





                                                        share|improve this answer























                                                        • is this still considered the best way to return a value from a promise or async/await?
                                                          – edwardsmarkf
                                                          Sep 26 at 20:58










                                                        • @edwardsmarkf Personally I don't think there's a best way as such. I use promises with then/catch , async/await as well as generators for async portions of my code. It largely depends on the context of usage.
                                                          – Anish K.
                                                          Oct 3 at 16:12















                                                        up vote
                                                        35
                                                        down vote













                                                        It's a very common issue we face while struggling with the 'mysteries' of JavaScript. Let me try demystifying this mystery today.



                                                        Let's start with a simple JavaScript function:



                                                        function foo(){
                                                        // do something
                                                        return 'wohoo';
                                                        }

                                                        let bar = foo(); // bar is 'wohoo' here


                                                        That's a simple synchronous function call (where each line of code is 'finished with its job' before the next one in sequence), and the result is same as expected.



                                                        Now let's add a bit of twist, by introducing little delay in our function, so that all lines of code are not 'finished' in sequence. Thus, it will emulate the asynchronous behavior of function :



                                                        function foo(){
                                                        setTimeout( ()=>{
                                                        return 'wohoo';
                                                        }, 1000 )
                                                        }

                                                        let bar = foo() // bar is undefined here


                                                        So there you go, that delay just broke the functionality we expected! But what exactly happened ? Well, it's actually pretty logical if you look at the code. the function foo(), upon execution, returns nothing (thus returned value is undefined), but it does start a timer, which executes a function after 1s to return 'wohoo'. But as you can see, the value that's assigned to bar is the immediately returned stuff from foo(), not anything else that comes later.



                                                        So, how do we tackle this issue?



                                                        Let's ask our function for a PROMISE.
                                                        Promise is really about what it means : it means that the function guarantees you to provide with any output it gets in future. so let's see it in action for our little problem above :



                                                        function foo(){
                                                        return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
                                                        setTimeout ( function(){
                                                        // promise is RESOLVED , when execution reaches this line of code
                                                        resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
                                                        }, 1000 )
                                                        })
                                                        }

                                                        let bar ;
                                                        foo().then( res => {
                                                        bar = res;
                                                        console.log(bar) // will print 'wohoo'
                                                        });


                                                        Thus, the summary is - to tackle the asynchronous functions like ajax based calls etc., you can use a promise to resolve the value (which you intend to return). Thus, in short you resolve value instead of returning, in asynchronous functions.



                                                        UPDATE (Promises with async/await)



                                                        Apart from using then/catch to work with promises, there exists one more approach. The idea is to recognize an asynchronous function and then wait for the promises to resolve, before moving to the next line of code. It's still just the promises under the hood, but with a different syntactical approach. To make things clearer, you can find a comparison below:



                                                        then/catch version:



                                                        function fetchUsers(){
                                                        let users = ;
                                                        getUsers()
                                                        .then(_users => users = _users)
                                                        .catch(err =>{
                                                        throw err
                                                        })
                                                        return users;
                                                        }


                                                        async/await version:



                                                          async function fetchUsers(){
                                                        try{
                                                        let users = await getUsers()
                                                        return users;
                                                        }
                                                        catch(err){
                                                        throw err;
                                                        }
                                                        }





                                                        share|improve this answer























                                                        • is this still considered the best way to return a value from a promise or async/await?
                                                          – edwardsmarkf
                                                          Sep 26 at 20:58










                                                        • @edwardsmarkf Personally I don't think there's a best way as such. I use promises with then/catch , async/await as well as generators for async portions of my code. It largely depends on the context of usage.
                                                          – Anish K.
                                                          Oct 3 at 16:12













                                                        up vote
                                                        35
                                                        down vote










                                                        up vote
                                                        35
                                                        down vote









                                                        It's a very common issue we face while struggling with the 'mysteries' of JavaScript. Let me try demystifying this mystery today.



                                                        Let's start with a simple JavaScript function:



                                                        function foo(){
                                                        // do something
                                                        return 'wohoo';
                                                        }

                                                        let bar = foo(); // bar is 'wohoo' here


                                                        That's a simple synchronous function call (where each line of code is 'finished with its job' before the next one in sequence), and the result is same as expected.



                                                        Now let's add a bit of twist, by introducing little delay in our function, so that all lines of code are not 'finished' in sequence. Thus, it will emulate the asynchronous behavior of function :



                                                        function foo(){
                                                        setTimeout( ()=>{
                                                        return 'wohoo';
                                                        }, 1000 )
                                                        }

                                                        let bar = foo() // bar is undefined here


                                                        So there you go, that delay just broke the functionality we expected! But what exactly happened ? Well, it's actually pretty logical if you look at the code. the function foo(), upon execution, returns nothing (thus returned value is undefined), but it does start a timer, which executes a function after 1s to return 'wohoo'. But as you can see, the value that's assigned to bar is the immediately returned stuff from foo(), not anything else that comes later.



                                                        So, how do we tackle this issue?



                                                        Let's ask our function for a PROMISE.
                                                        Promise is really about what it means : it means that the function guarantees you to provide with any output it gets in future. so let's see it in action for our little problem above :



                                                        function foo(){
                                                        return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
                                                        setTimeout ( function(){
                                                        // promise is RESOLVED , when execution reaches this line of code
                                                        resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
                                                        }, 1000 )
                                                        })
                                                        }

                                                        let bar ;
                                                        foo().then( res => {
                                                        bar = res;
                                                        console.log(bar) // will print 'wohoo'
                                                        });


                                                        Thus, the summary is - to tackle the asynchronous functions like ajax based calls etc., you can use a promise to resolve the value (which you intend to return). Thus, in short you resolve value instead of returning, in asynchronous functions.



                                                        UPDATE (Promises with async/await)



                                                        Apart from using then/catch to work with promises, there exists one more approach. The idea is to recognize an asynchronous function and then wait for the promises to resolve, before moving to the next line of code. It's still just the promises under the hood, but with a different syntactical approach. To make things clearer, you can find a comparison below:



                                                        then/catch version:



                                                        function fetchUsers(){
                                                        let users = ;
                                                        getUsers()
                                                        .then(_users => users = _users)
                                                        .catch(err =>{
                                                        throw err
                                                        })
                                                        return users;
                                                        }


                                                        async/await version:



                                                          async function fetchUsers(){
                                                        try{
                                                        let users = await getUsers()
                                                        return users;
                                                        }
                                                        catch(err){
                                                        throw err;
                                                        }
                                                        }





                                                        share|improve this answer














                                                        It's a very common issue we face while struggling with the 'mysteries' of JavaScript. Let me try demystifying this mystery today.



                                                        Let's start with a simple JavaScript function:



                                                        function foo(){
                                                        // do something
                                                        return 'wohoo';
                                                        }

                                                        let bar = foo(); // bar is 'wohoo' here


                                                        That's a simple synchronous function call (where each line of code is 'finished with its job' before the next one in sequence), and the result is same as expected.



                                                        Now let's add a bit of twist, by introducing little delay in our function, so that all lines of code are not 'finished' in sequence. Thus, it will emulate the asynchronous behavior of function :



                                                        function foo(){
                                                        setTimeout( ()=>{
                                                        return 'wohoo';
                                                        }, 1000 )
                                                        }

                                                        let bar = foo() // bar is undefined here


                                                        So there you go, that delay just broke the functionality we expected! But what exactly happened ? Well, it's actually pretty logical if you look at the code. the function foo(), upon execution, returns nothing (thus returned value is undefined), but it does start a timer, which executes a function after 1s to return 'wohoo'. But as you can see, the value that's assigned to bar is the immediately returned stuff from foo(), not anything else that comes later.



                                                        So, how do we tackle this issue?



                                                        Let's ask our function for a PROMISE.
                                                        Promise is really about what it means : it means that the function guarantees you to provide with any output it gets in future. so let's see it in action for our little problem above :



                                                        function foo(){
                                                        return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
                                                        setTimeout ( function(){
                                                        // promise is RESOLVED , when execution reaches this line of code
                                                        resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
                                                        }, 1000 )
                                                        })
                                                        }

                                                        let bar ;
                                                        foo().then( res => {
                                                        bar = res;
                                                        console.log(bar) // will print 'wohoo'
                                                        });


                                                        Thus, the summary is - to tackle the asynchronous functions like ajax based calls etc., you can use a promise to resolve the value (which you intend to return). Thus, in short you resolve value instead of returning, in asynchronous functions.



                                                        UPDATE (Promises with async/await)



                                                        Apart from using then/catch to work with promises, there exists one more approach. The idea is to recognize an asynchronous function and then wait for the promises to resolve, before moving to the next line of code. It's still just the promises under the hood, but with a different syntactical approach. To make things clearer, you can find a comparison below:



                                                        then/catch version:



                                                        function fetchUsers(){
                                                        let users = ;
                                                        getUsers()
                                                        .then(_users => users = _users)
                                                        .catch(err =>{
                                                        throw err
                                                        })
                                                        return users;
                                                        }


                                                        async/await version:



                                                          async function fetchUsers(){
                                                        try{
                                                        let users = await getUsers()
                                                        return users;
                                                        }
                                                        catch(err){
                                                        throw err;
                                                        }
                                                        }






                                                        share|improve this answer














                                                        share|improve this answer



                                                        share|improve this answer








                                                        edited Oct 9 at 17:33

























                                                        answered Oct 31 '17 at 20:12









                                                        Anish K.

                                                        6451017




                                                        6451017












                                                        • is this still considered the best way to return a value from a promise or async/await?
                                                          – edwardsmarkf
                                                          Sep 26 at 20:58










                                                        • @edwardsmarkf Personally I don't think there's a best way as such. I use promises with then/catch , async/await as well as generators for async portions of my code. It largely depends on the context of usage.
                                                          – Anish K.
                                                          Oct 3 at 16:12


















                                                        • is this still considered the best way to return a value from a promise or async/await?
                                                          – edwardsmarkf
                                                          Sep 26 at 20:58










                                                        • @edwardsmarkf Personally I don't think there's a best way as such. I use promises with then/catch , async/await as well as generators for async portions of my code. It largely depends on the context of usage.
                                                          – Anish K.
                                                          Oct 3 at 16:12
















                                                        is this still considered the best way to return a value from a promise or async/await?
                                                        – edwardsmarkf
                                                        Sep 26 at 20:58




                                                        is this still considered the best way to return a value from a promise or async/await?
                                                        – edwardsmarkf
                                                        Sep 26 at 20:58












                                                        @edwardsmarkf Personally I don't think there's a best way as such. I use promises with then/catch , async/await as well as generators for async portions of my code. It largely depends on the context of usage.
                                                        – Anish K.
                                                        Oct 3 at 16:12




                                                        @edwardsmarkf Personally I don't think there's a best way as such. I use promises with then/catch , async/await as well as generators for async portions of my code. It largely depends on the context of usage.
                                                        – Anish K.
                                                        Oct 3 at 16:12










                                                        up vote
                                                        31
                                                        down vote













                                                        Here are some approaches to work with asynchronous requests:




                                                        1. Browser Promise object


                                                        2. Q - A promise library for JavaScript

                                                        3. A+ Promises.js

                                                        4. jQuery deferred

                                                        5. XMLHttpRequest API

                                                        6. Using callback concept - As implementation in first answer


                                                        Example: jQuery deferred implementation to work with multiple requests






                                                        var App = App || {};

                                                        App = {
                                                        getDataFromServer: function(){

                                                        var self = this,
                                                        deferred = $.Deferred(),
                                                        requests = ;

                                                        requests.push($.getJSON('request/ajax/url/1'));
                                                        requests.push($.getJSON('request/ajax/url/2'));

                                                        $.when.apply(jQuery, requests).done(function(xhrResponse) {
                                                        return deferred.resolve(xhrResponse.result);
                                                        });
                                                        return deferred;
                                                        },

                                                        init: function(){

                                                        this.getDataFromServer().done(_.bind(function(resp1, resp2) {

                                                        // Do the operations which you wanted to do when you
                                                        // get a response from Ajax, for example, log response.
                                                        }, this));
                                                        }
                                                        };
                                                        App.init();








                                                        share|improve this answer



























                                                          up vote
                                                          31
                                                          down vote













                                                          Here are some approaches to work with asynchronous requests:




                                                          1. Browser Promise object


                                                          2. Q - A promise library for JavaScript

                                                          3. A+ Promises.js

                                                          4. jQuery deferred

                                                          5. XMLHttpRequest API

                                                          6. Using callback concept - As implementation in first answer


                                                          Example: jQuery deferred implementation to work with multiple requests






                                                          var App = App || {};

                                                          App = {
                                                          getDataFromServer: function(){

                                                          var self = this,
                                                          deferred = $.Deferred(),
                                                          requests = ;

                                                          requests.push($.getJSON('request/ajax/url/1'));
                                                          requests.push($.getJSON('request/ajax/url/2'));

                                                          $.when.apply(jQuery, requests).done(function(xhrResponse) {
                                                          return deferred.resolve(xhrResponse.result);
                                                          });
                                                          return deferred;
                                                          },

                                                          init: function(){

                                                          this.getDataFromServer().done(_.bind(function(resp1, resp2) {

                                                          // Do the operations which you wanted to do when you
                                                          // get a response from Ajax, for example, log response.
                                                          }, this));
                                                          }
                                                          };
                                                          App.init();








                                                          share|improve this answer

























                                                            up vote
                                                            31
                                                            down vote










                                                            up vote
                                                            31
                                                            down vote









                                                            Here are some approaches to work with asynchronous requests:




                                                            1. Browser Promise object


                                                            2. Q - A promise library for JavaScript

                                                            3. A+ Promises.js

                                                            4. jQuery deferred

                                                            5. XMLHttpRequest API

                                                            6. Using callback concept - As implementation in first answer


                                                            Example: jQuery deferred implementation to work with multiple requests






                                                            var App = App || {};

                                                            App = {
                                                            getDataFromServer: function(){

                                                            var self = this,
                                                            deferred = $.Deferred(),
                                                            requests = ;

                                                            requests.push($.getJSON('request/ajax/url/1'));
                                                            requests.push($.getJSON('request/ajax/url/2'));

                                                            $.when.apply(jQuery, requests).done(function(xhrResponse) {
                                                            return deferred.resolve(xhrResponse.result);
                                                            });
                                                            return deferred;
                                                            },

                                                            init: function(){

                                                            this.getDataFromServer().done(_.bind(function(resp1, resp2) {

                                                            // Do the operations which you wanted to do when you
                                                            // get a response from Ajax, for example, log response.
                                                            }, this));
                                                            }
                                                            };
                                                            App.init();








                                                            share|improve this answer














                                                            Here are some approaches to work with asynchronous requests:




                                                            1. Browser Promise object


                                                            2. Q - A promise library for JavaScript

                                                            3. A+ Promises.js

                                                            4. jQuery deferred

                                                            5. XMLHttpRequest API

                                                            6. Using callback concept - As implementation in first answer


                                                            Example: jQuery deferred implementation to work with multiple requests






                                                            var App = App || {};

                                                            App = {
                                                            getDataFromServer: function(){

                                                            var self = this,
                                                            deferred = $.Deferred(),
                                                            requests = ;

                                                            requests.push($.getJSON('request/ajax/url/1'));
                                                            requests.push($.getJSON('request/ajax/url/2'));

                                                            $.when.apply(jQuery, requests).done(function(xhrResponse) {
                                                            return deferred.resolve(xhrResponse.result);
                                                            });
                                                            return deferred;
                                                            },

                                                            init: function(){

                                                            this.getDataFromServer().done(_.bind(function(resp1, resp2) {

                                                            // Do the operations which you wanted to do when you
                                                            // get a response from Ajax, for example, log response.
                                                            }, this));
                                                            }
                                                            };
                                                            App.init();








                                                            var App = App || {};

                                                            App = {
                                                            getDataFromServer: function(){

                                                            var self = this,
                                                            deferred = $.Deferred(),
                                                            requests = ;

                                                            requests.push($.getJSON('request/ajax/url/1'));
                                                            requests.push($.getJSON('request/ajax/url/2'));

                                                            $.when.apply(jQuery, requests).done(function(xhrResponse) {
                                                            return deferred.resolve(xhrResponse.result);
                                                            });
                                                            return deferred;
                                                            },

                                                            init: function(){

                                                            this.getDataFromServer().done(_.bind(function(resp1, resp2) {

                                                            // Do the operations which you wanted to do when you
                                                            // get a response from Ajax, for example, log response.
                                                            }, this));
                                                            }
                                                            };
                                                            App.init();





                                                            var App = App || {};

                                                            App = {
                                                            getDataFromServer: function(){

                                                            var self = this,
                                                            deferred = $.Deferred(),
                                                            requests = ;

                                                            requests.push($.getJSON('request/ajax/url/1'));
                                                            requests.push($.getJSON('request/ajax/url/2'));

                                                            $.when.apply(jQuery, requests).done(function(xhrResponse) {
                                                            return deferred.resolve(xhrResponse.result);
                                                            });
                                                            return deferred;
                                                            },

                                                            init: function(){

                                                            this.getDataFromServer().done(_.bind(function(resp1, resp2) {

                                                            // Do the operations which you wanted to do when you
                                                            // get a response from Ajax, for example, log response.
                                                            }, this));
                                                            }
                                                            };
                                                            App.init();






                                                            share|improve this answer














                                                            share|improve this answer



                                                            share|improve this answer








                                                            edited Jun 22 '17 at 9:31

























                                                            answered Aug 13 '16 at 9:36









                                                            Mohan Dere

                                                            2,41411013




                                                            2,41411013






















                                                                up vote
                                                                30
                                                                down vote













                                                                ECMAScript 6 has 'generators' which allow you to easily program in an asynchronous style.



                                                                function* myGenerator() {
                                                                const callback = yield;
                                                                let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
                                                                console.log("response is:", response);

                                                                // examples of other things you can do
                                                                yield setTimeout(callback, 1000);
                                                                console.log("it delayed for 1000ms");
                                                                while (response.statusText === "error") {
                                                                [response] = yield* anotherGenerator();
                                                                }
                                                                }


                                                                To run the above code you do this:



                                                                const gen = myGenerator(); // Create generator
                                                                gen.next(); // Start it
                                                                gen.next((...args) => gen.next([...args])); // Set its callback function


                                                                If you need to target browsers that don't support ES6 you can run the code through Babel or closure-compiler to generate ECMAScript 5.



                                                                The callback ...args are wrapped in an array and destructured when you read them so that the pattern can cope with callbacks that have multiple arguments. For example with node fs:



                                                                const [err, data] = yield fs.readFile(filePath, "utf-8", callback);





                                                                share|improve this answer



















                                                                • 4




                                                                  I would be interested to know why this is down-voted. It seems a good simple answer that has not been previously given.
                                                                  – James
                                                                  Feb 17 at 17:49










                                                                • People probably just assume answers at the end are repeats or spam.
                                                                  – ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000
                                                                  Mar 1 at 1:08















                                                                up vote
                                                                30
                                                                down vote













                                                                ECMAScript 6 has 'generators' which allow you to easily program in an asynchronous style.



                                                                function* myGenerator() {
                                                                const callback = yield;
                                                                let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
                                                                console.log("response is:", response);

                                                                // examples of other things you can do
                                                                yield setTimeout(callback, 1000);
                                                                console.log("it delayed for 1000ms");
                                                                while (response.statusText === "error") {
                                                                [response] = yield* anotherGenerator();
                                                                }
                                                                }


                                                                To run the above code you do this:



                                                                const gen = myGenerator(); // Create generator
                                                                gen.next(); // Start it
                                                                gen.next((...args) => gen.next([...args])); // Set its callback function


                                                                If you need to target browsers that don't support ES6 you can run the code through Babel or closure-compiler to generate ECMAScript 5.



                                                                The callback ...args are wrapped in an array and destructured when you read them so that the pattern can cope with callbacks that have multiple arguments. For example with node fs:



                                                                const [err, data] = yield fs.readFile(filePath, "utf-8", callback);





                                                                share|improve this answer



















                                                                • 4




                                                                  I would be interested to know why this is down-voted. It seems a good simple answer that has not been previously given.
                                                                  – James
                                                                  Feb 17 at 17:49










                                                                • People probably just assume answers at the end are repeats or spam.
                                                                  – ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000
                                                                  Mar 1 at 1:08













                                                                up vote
                                                                30
                                                                down vote










                                                                up vote
                                                                30
                                                                down vote









                                                                ECMAScript 6 has 'generators' which allow you to easily program in an asynchronous style.



                                                                function* myGenerator() {
                                                                const callback = yield;
                                                                let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
                                                                console.log("response is:", response);

                                                                // examples of other things you can do
                                                                yield setTimeout(callback, 1000);
                                                                console.log("it delayed for 1000ms");
                                                                while (response.statusText === "error") {
                                                                [response] = yield* anotherGenerator();
                                                                }
                                                                }


                                                                To run the above code you do this:



                                                                const gen = myGenerator(); // Create generator
                                                                gen.next(); // Start it
                                                                gen.next((...args) => gen.next([...args])); // Set its callback function


                                                                If you need to target browsers that don't support ES6 you can run the code through Babel or closure-compiler to generate ECMAScript 5.



                                                                The callback ...args are wrapped in an array and destructured when you read them so that the pattern can cope with callbacks that have multiple arguments. For example with node fs:



                                                                const [err, data] = yield fs.readFile(filePath, "utf-8", callback);





                                                                share|improve this answer














                                                                ECMAScript 6 has 'generators' which allow you to easily program in an asynchronous style.



                                                                function* myGenerator() {
                                                                const callback = yield;
                                                                let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
                                                                console.log("response is:", response);

                                                                // examples of other things you can do
                                                                yield setTimeout(callback, 1000);
                                                                console.log("it delayed for 1000ms");
                                                                while (response.statusText === "error") {
                                                                [response] = yield* anotherGenerator();
                                                                }
                                                                }


                                                                To run the above code you do this:



                                                                const gen = myGenerator(); // Create generator
                                                                gen.next(); // Start it
                                                                gen.next((...args) => gen.next([...args])); // Set its callback function


                                                                If you need to target browsers that don't support ES6 you can run the code through Babel or closure-compiler to generate ECMAScript 5.



                                                                The callback ...args are wrapped in an array and destructured when you read them so that the pattern can cope with callbacks that have multiple arguments. For example with node fs:



                                                                const [err, data] = yield fs.readFile(filePath, "utf-8", callback);






                                                                share|improve this answer














                                                                share|improve this answer



                                                                share|improve this answer








                                                                edited Jul 31 at 10:35

























                                                                answered Feb 17 at 15:26









                                                                James

                                                                2,9611728




                                                                2,9611728








                                                                • 4




                                                                  I would be interested to know why this is down-voted. It seems a good simple answer that has not been previously given.
                                                                  – James
                                                                  Feb 17 at 17:49










                                                                • People probably just assume answers at the end are repeats or spam.
                                                                  – ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000
                                                                  Mar 1 at 1:08














                                                                • 4




                                                                  I would be interested to know why this is down-voted. It seems a good simple answer that has not been previously given.
                                                                  – James
                                                                  Feb 17 at 17:49










                                                                • People probably just assume answers at the end are repeats or spam.
                                                                  – ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000
                                                                  Mar 1 at 1:08








                                                                4




                                                                4




                                                                I would be interested to know why this is down-voted. It seems a good simple answer that has not been previously given.
                                                                – James
                                                                Feb 17 at 17:49




                                                                I would be interested to know why this is down-voted. It seems a good simple answer that has not been previously given.
                                                                – James
                                                                Feb 17 at 17:49












                                                                People probably just assume answers at the end are repeats or spam.
                                                                – ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000
                                                                Mar 1 at 1:08




                                                                People probably just assume answers at the end are repeats or spam.
                                                                – ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000
                                                                Mar 1 at 1:08










                                                                up vote
                                                                28
                                                                down vote













                                                                Use a callback() function inside the foo() success.
                                                                Try in this way. It is simple and easy to understand.  



                                                                var lat = "";
                                                                var lon = "";
                                                                function callback(data) {
                                                                lat = data.lat;
                                                                lon = data.lon;
                                                                }
                                                                function getLoc() {
                                                                var url = "http://ip-api.com/json"
                                                                $.getJSON(url, function(data) {
                                                                callback(data);
                                                                });
                                                                }

                                                                getLoc();





                                                                share|improve this answer



























                                                                  up vote
                                                                  28
                                                                  down vote













                                                                  Use a callback() function inside the foo() success.
                                                                  Try in this way. It is simple and easy to understand.  



                                                                  var lat = "";
                                                                  var lon = "";
                                                                  function callback(data) {
                                                                  lat = data.lat;
                                                                  lon = data.lon;
                                                                  }
                                                                  function getLoc() {
                                                                  var url = "http://ip-api.com/json"
                                                                  $.getJSON(url, function(data) {
                                                                  callback(data);
                                                                  });
                                                                  }

                                                                  getLoc();





                                                                  share|improve this answer

























                                                                    up vote
                                                                    28
                                                                    down vote










                                                                    up vote
                                                                    28
                                                                    down vote









                                                                    Use a callback() function inside the foo() success.
                                                                    Try in this way. It is simple and easy to understand.  



                                                                    var lat = "";
                                                                    var lon = "";
                                                                    function callback(data) {
                                                                    lat = data.lat;
                                                                    lon = data.lon;
                                                                    }
                                                                    function getLoc() {
                                                                    var url = "http://ip-api.com/json"
                                                                    $.getJSON(url, function(data) {
                                                                    callback(data);
                                                                    });
                                                                    }

                                                                    getLoc();





                                                                    share|improve this answer














                                                                    Use a callback() function inside the foo() success.
                                                                    Try in this way. It is simple and easy to understand.  



                                                                    var lat = "";
                                                                    var lon = "";
                                                                    function callback(data) {
                                                                    lat = data.lat;
                                                                    lon = data.lon;
                                                                    }
                                                                    function getLoc() {
                                                                    var url = "http://ip-api.com/json"
                                                                    $.getJSON(url, function(data) {
                                                                    callback(data);
                                                                    });
                                                                    }

                                                                    getLoc();






                                                                    share|improve this answer














                                                                    share|improve this answer



                                                                    share|improve this answer








                                                                    edited Nov 17 '17 at 9:15









                                                                    Alex Weitz

                                                                    1,47021526




                                                                    1,47021526










                                                                    answered Apr 24 '17 at 8:09









                                                                    Mahfuzur Rahman

                                                                    810818




                                                                    810818






















                                                                        up vote
                                                                        26
                                                                        down vote













                                                                        Short answer: Your foo() method returns immediately, while the $ajax() call executes asynchronously after the function returns. The problem is then how or where to store the results retrieved by the async call once it returns.



                                                                        Several solutions have been given in this thread. Perhaps the easiest way is to pass an object to the foo() method, and to store the results in a member of that object after the async call completes.



                                                                        function foo(result) {
                                                                        $.ajax({
                                                                        url: '...',
                                                                        success: function(response) {
                                                                        result.response = response; // Store the async result
                                                                        }
                                                                        });
                                                                        }

                                                                        var result = { response: null }; // Object to hold the async result
                                                                        foo(result); // Returns before the async completes


                                                                        Note that the call to foo() will still return nothing useful. However, the result of the async call will now be stored in result.response.






                                                                        share|improve this answer

















                                                                        • 11




                                                                          While this works, it's not really better than assigning to a global variable.
                                                                          – Felix Kling
                                                                          Sep 23 '15 at 22:53















                                                                        up vote
                                                                        26
                                                                        down vote













                                                                        Short answer: Your foo() method returns immediately, while the $ajax() call executes asynchronously after the function returns. The problem is then how or where to store the results retrieved by the async call once it returns.



                                                                        Several solutions have been given in this thread. Perhaps the easiest way is to pass an object to the foo() method, and to store the results in a member of that object after the async call completes.



                                                                        function foo(result) {
                                                                        $.ajax({
                                                                        url: '...',
                                                                        success: function(response) {
                                                                        result.response = response; // Store the async result
                                                                        }
                                                                        });
                                                                        }

                                                                        var result = { response: null }; // Object to hold the async result
                                                                        foo(result); // Returns before the async completes


                                                                        Note that the call to foo() will still return nothing useful. However, the result of the async call will now be stored in result.response.






                                                                        share|improve this answer

















                                                                        • 11




                                                                          While this works, it's not really better than assigning to a global variable.
                                                                          – Felix Kling
                                                                          Sep 23 '15 at 22:53













                                                                        up vote
                                                                        26
                                                                        down vote










                                                                        up vote
                                                                        26
                                                                        down vote









                                                                        Short answer: Your foo() method returns immediately, while the $ajax() call executes asynchronously after the function returns. The problem is then how or where to store the results retrieved by the async call once it returns.



                                                                        Several solutions have been given in this thread. Perhaps the easiest way is to pass an object to the foo() method, and to store the results in a member of that object after the async call completes.



                                                                        function foo(result) {
                                                                        $.ajax({
                                                                        url: '...',
                                                                        success: function(response) {
                                                                        result.response = response; // Store the async result
                                                                        }
                                                                        });
                                                                        }

                                                                        var result = { response: null }; // Object to hold the async result
                                                                        foo(result); // Returns before the async completes


                                                                        Note that the call to foo() will still return nothing useful. However, the result of the async call will now be stored in result.response.






                                                                        share|improve this answer












                                                                        Short answer: Your foo() method returns immediately, while the $ajax() call executes asynchronously after the function returns. The problem is then how or where to store the results retrieved by the async call once it returns.



                                                                        Several solutions have been given in this thread. Perhaps the easiest way is to pass an object to the foo() method, and to store the results in a member of that object after the async call completes.



                                                                        function foo(result) {
                                                                        $.ajax({
                                                                        url: '...',
                                                                        success: function(response) {
                                                                        result.response = response; // Store the async result
                                                                        }
                                                                        });
                                                                        }

                                                                        var result = { response: null }; // Object to hold the async result
                                                                        foo(result); // Returns before the async completes


                                                                        Note that the call to foo() will still return nothing useful. However, the result of the async call will now be stored in result.response.







                                                                        share|improve this answer












                                                                        share|improve this answer



                                                                        share|improve this answer










                                                                        answered Sep 23 '15 at 22:52









                                                                        David R Tribble

                                                                        8,49323248




                                                                        8,49323248








                                                                        • 11




                                                                          While this works, it's not really better than assigning to a global variable.
                                                                          – Felix Kling
                                                                          Sep 23 '15 at 22:53














                                                                        • 11




                                                                          While this works, it's not really better than assigning to a global variable.
                                                                          – Felix Kling
                                                                          Sep 23 '15 at 22:53








                                                                        11




                                                                        11




                                                                        While this works, it's not really better than assigning to a global variable.
                                                                        – Felix Kling
                                                                        Sep 23 '15 at 22:53




                                                                        While this works, it's not really better than assigning to a global variable.
                                                                        – Felix Kling
                                                                        Sep 23 '15 at 22:53










                                                                        up vote
                                                                        20
                                                                        down vote













                                                                        Of course there are many approaches like synchronous request, promise, but from my experience I think you should use the callback approach. It's natural to asynchronous behavior of Javascript.
                                                                        So, your code snippet can be rewrite a little different:



                                                                        function foo() {
                                                                        var result;

                                                                        $.ajax({
                                                                        url: '...',
                                                                        success: function(response) {
                                                                        myCallback(response);
                                                                        }
                                                                        });

                                                                        return result;
                                                                        }

                                                                        function myCallback(response) {
                                                                        // Does something.
                                                                        }





                                                                        share|improve this answer



















                                                                        • 4




                                                                          There's nothing inherently asynchronous about callbacks or JavaScript.
                                                                          – Aluan Haddad
                                                                          Mar 18 at 19:48















                                                                        up vote
                                                                        20
                                                                        down vote













                                                                        Of course there are many approaches like synchronous request, promise, but from my experience I think you should use the callback approach. It's natural to asynchronous behavior of Javascript.
                                                                        So, your code snippet can be rewrite a little different:



                                                                        function foo() {
                                                                        var result;

                                                                        $.ajax({
                                                                        url: '...',
                                                                        success: function(response) {
                                                                        myCallback(response);
                                                                        }
                                                                        });

                                                                        return result;
                                                                        }

                                                                        function myCallback(response) {
                                                                        // Does something.
                                                                        }





                                                                        share|improve this answer



















                                                                        • 4




                                                                          There's nothing inherently asynchronous about callbacks or JavaScript.
                                                                          – Aluan Haddad
                                                                          Mar 18 at 19:48













                                                                        up vote
                                                                        20
                                                                        down vote










                                                                        up vote
                                                                        20
                                                                        down vote









                                                                        Of course there are many approaches like synchronous request, promise, but from my experience I think you should use the callback approach. It's natural to asynchronous behavior of Javascript.
                                                                        So, your code snippet can be rewrite a little different:



                                                                        function foo() {
                                                                        var result;

                                                                        $.ajax({
                                                                        url: '...',
                                                                        success: function(response) {
                                                                        myCallback(response);
                                                                        }
                                                                        });

                                                                        return result;
                                                                        }

                                                                        function myCallback(response) {
                                                                        // Does something.
                                                                        }





                                                                        share|improve this answer














                                                                        Of course there are many approaches like synchronous request, promise, but from my experience I think you should use the callback approach. It's natural to asynchronous behavior of Javascript.
                                                                        So, your code snippet can be rewrite a little different:



                                                                        function foo() {
                                                                        var result;

                                                                        $.ajax({
                                                                        url: '...',
                                                                        success: function(response) {
                                                                        myCallback(response);
                                                                        }
                                                                        });

                                                                        return result;
                                                                        }

                                                                        function myCallback(response) {
                                                                        // Does something.
                                                                        }






                                                                        share|improve this answer














                                                                        share|improve this answer



                                                                        share|improve this answer








                                                                        edited Mar 7 at 14:23









                                                                        Michał Perłakowski

                                                                        41.1k1698115




                                                                        41.1k1698115










                                                                        answered Jul 5 '17 at 20:28









                                                                        Khoa Bui

                                                                        328413




                                                                        328413








                                                                        • 4




                                                                          There's nothing inherently asynchronous about callbacks or JavaScript.
                                                                          – Aluan Haddad
                                                                          Mar 18 at 19:48














                                                                        • 4




                                                                          There's nothing inherently asynchronous about callbacks or JavaScript.
                                                                          – Aluan Haddad
                                                                          Mar 18 at 19:48








                                                                        4




                                                                        4




                                                                        There's nothing inherently asynchronous about callbacks or JavaScript.
                                                                        – Aluan Haddad
                                                                        Mar 18 at 19:48




                                                                        There's nothing inherently asynchronous about callbacks or JavaScript.
                                                                        – Aluan Haddad
                                                                        Mar 18 at 19:48










                                                                        up vote
                                                                        20
                                                                        down vote













                                                                        The question was:




                                                                        How do I return the response from an asynchronous call?




                                                                        which CAN be interpreted as:




                                                                        How to make asynchronous code look synchronous?




                                                                        The solution will be to avoid callbacks, and use a combination of Promises and async/await.



                                                                        I would like to give an example for a Ajax request.



                                                                        (Although it can be written in Javascript, I prefer to write it in Python, and compile it to Javascript using Transcrypt. It will be clear enough.)



                                                                        Lets first enable JQuery usage, to have $ available as S:



                                                                        __pragma__ ('alias', 'S', '$')


                                                                        Define a function which returns a Promise, in this case an Ajax call:



                                                                        def read(url: str):
                                                                        deferred = S.Deferred()
                                                                        S.ajax({'type': "POST", 'url': url, 'data': { },
                                                                        'success': lambda d: deferred.resolve(d),
                                                                        'error': lambda e: deferred.reject(e)
                                                                        })
                                                                        return deferred.promise()


                                                                        Use the asynchronous code as if it were synchronous:



                                                                        async def readALot():
                                                                        try:
                                                                        result1 = await read("url_1")
                                                                        result2 = await read("url_2")
                                                                        except Exception:
                                                                        console.warn("Reading a lot failed")





                                                                        share|improve this answer



























                                                                          up vote
                                                                          20
                                                                          down vote













                                                                          The question was:




                                                                          How do I return the response from an asynchronous call?




                                                                          which CAN be interpreted as:




                                                                          How to make asynchronous code look synchronous?




                                                                          The solution will be to avoid callbacks, and use a combination of Promises and async/await.



                                                                          I would like to give an example for a Ajax request.



                                                                          (Although it can be written in Javascript, I prefer to write it in Python, and compile it to Javascript using Transcrypt. It will be clear enough.)



                                                                          Lets first enable JQuery usage, to have $ available as S:



                                                                          __pragma__ ('alias', 'S', '$')


                                                                          Define a function which returns a Promise, in this case an Ajax call:



                                                                          def read(url: str):
                                                                          deferred = S.Deferred()
                                                                          S.ajax({'type': "POST", 'url': url, 'data': { },
                                                                          'success': lambda d: deferred.resolve(d),
                                                                          'error': lambda e: deferred.reject(e)
                                                                          })
                                                                          return deferred.promise()


                                                                          Use the asynchronous code as if it were synchronous:



                                                                          async def readALot():
                                                                          try:
                                                                          result1 = await read("url_1")
                                                                          result2 = await read("url_2")
                                                                          except Exception:
                                                                          console.warn("Reading a lot failed")





                                                                          share|improve this answer

























                                                                            up vote
                                                                            20
                                                                            down vote










                                                                            up vote
                                                                            20
                                                                            down vote









                                                                            The question was:




                                                                            How do I return the response from an asynchronous call?




                                                                            which CAN be interpreted as:




                                                                            How to make asynchronous code look synchronous?




                                                                            The solution will be to avoid callbacks, and use a combination of Promises and async/await.



                                                                            I would like to give an example for a Ajax request.



                                                                            (Although it can be written in Javascript, I prefer to write it in Python, and compile it to Javascript using Transcrypt. It will be clear enough.)



                                                                            Lets first enable JQuery usage, to have $ available as S:



                                                                            __pragma__ ('alias', 'S', '$')


                                                                            Define a function which returns a Promise, in this case an Ajax call:



                                                                            def read(url: str):
                                                                            deferred = S.Deferred()
                                                                            S.ajax({'type': "POST", 'url': url, 'data': { },
                                                                            'success': lambda d: deferred.resolve(d),
                                                                            'error': lambda e: deferred.reject(e)
                                                                            })
                                                                            return deferred.promise()


                                                                            Use the asynchronous code as if it were synchronous:



                                                                            async def readALot():
                                                                            try:
                                                                            result1 = await read("url_1")
                                                                            result2 = await read("url_2")
                                                                            except Exception:
                                                                            console.warn("Reading a lot failed")





                                                                            share|improve this answer














                                                                            The question was:




                                                                            How do I return the response from an asynchronous call?




                                                                            which CAN be interpreted as:




                                                                            How to make asynchronous code look synchronous?




                                                                            The solution will be to avoid callbacks, and use a combination of Promises and async/await.



                                                                            I would like to give an example for a Ajax request.



                                                                            (Although it can be written in Javascript, I prefer to write it in Python, and compile it to Javascript using Transcrypt. It will be clear enough.)



                                                                            Lets first enable JQuery usage, to have $ available as S:



                                                                            __pragma__ ('alias', 'S', '$')


                                                                            Define a function which returns a Promise, in this case an Ajax call:



                                                                            def read(url: str):
                                                                            deferred = S.Deferred()
                                                                            S.ajax({'type': "POST", 'url': url, 'data': { },
                                                                            'success': lambda d: deferred.resolve(d),
                                                                            'error': lambda e: deferred.reject(e)
                                                                            })
                                                                            return deferred.promise()


                                                                            Use the asynchronous code as if it were synchronous:



                                                                            async def readALot():
                                                                            try:
                                                                            result1 = await read("url_1")
                                                                            result2 = await read("url_2")
                                                                            except Exception:
                                                                            console.warn("Reading a lot failed")






                                                                            share|improve this answer














                                                                            share|improve this answer



                                                                            share|improve this answer








                                                                            edited May 24 at 8:36

























                                                                            answered Jan 13 at 19:13









                                                                            Pieter Jan Bonestroo

                                                                            26627




                                                                            26627






















                                                                                up vote
                                                                                18
                                                                                down vote













                                                                                We find ourselves in a universe which appears to progress along a dimension we call "time". We don't really understand what time is, but we have developed abstractions and vocabulary that let us reason and talk about it: "past", "present", "future", "before", "after".



                                                                                The computer systems we build--more and more--have time as an important dimension. Certain things are set up to happen in the future. Then other things need to happen after those first things eventually occur. This is the basic notion called "asynchronicity". In our increasingly networked world, the most common case of asynchronicity is waiting for some remote system to respond to some request.



                                                                                Consider an example. You call the milkman and order some milk. When it comes, you want to put it in your coffee. You can't put the milk in your coffee right now, because it is not here yet. You have to wait for it to come before putting it in your coffee. In other words, the following won't work:



                                                                                var milk = order_milk();
                                                                                put_in_coffee(milk);


                                                                                Because JS has no way to know that it needs to wait for order_milk to finish before it executes put_in_coffee. In other words, it does not know that order_milk is asynchronous--is something that is not going to result in milk until some future time. JS, and other declarative languages execute one statement after another without waiting.



                                                                                The classic JS approach to this problem, taking advantage of the fact that JS supports functions as first-class objects which can be passed around, is to pass a function as a parameter to the asynchronous request, which it will then invoke when it has completed its task sometime in the future. That is the "callback" approach. It looks like this:



                                                                                order_milk(put_in_coffee);


                                                                                order_milk kicks off, orders the milk, then, when and only when it arrives, it invokes put_in_coffee.



                                                                                The problem with this callback approach is that it pollutes the normal semantics of a function reporting its result with return; instead, functions must not reports their results by calling a callback given as a parameter. Also, this approach can rapidly become unwieldy when dealing with longer sequences of events. For example, let's say that I want to wait for the milk to be put in the coffee, and then and only then perform a third step, namely drinking the coffee. I end up needing to write something like this:



                                                                                order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }


                                                                                where I am passing to put_in_coffee both the milk to put in it, and also the action (drink_coffee) to execute once the milk has been put in. Such code becomes hard to write, and read, and debug.



                                                                                In this case, we could rewrite the code in the question as:



                                                                                var answer;
                                                                                $.ajax('/foo.json') . done(function(response) {
                                                                                callback(response.data);
                                                                                });

                                                                                function callback(data) {
                                                                                console.log(data);
                                                                                }


                                                                                Enter promises



                                                                                This was the motivation for the notion of a "promise", which is a particular type of value which represents a future or asynchronous outcome of some sort. It can represent something that already happened, or that is going to happen in the future, or might never happen at all. Promises have a single method, named then, to which you pass an action to be executed when the outcome the promise represents has been realized.



                                                                                In the case of our milk and coffee, we design order_milk to return a promise for the milk arriving, then specify put_in_coffee as a then action, as follows:



                                                                                order_milk() . then(put_in_coffee)


                                                                                One advantage of this is that we can string these together to create sequences of future occurrences ("chaining"):



                                                                                order_milk() . then(put_in_coffee) . then(drink_coffee)


                                                                                Let's apply promises to your particular problem. We will wrap our request logic inside a function, which returns a promise:



                                                                                function get_data() {
                                                                                return $.ajax('/foo.json');
                                                                                }


                                                                                Actually, all we've done is added a return to the call to $.ajax. This works because jQuery's $.ajax already returns a kind of promise-like thing. (In practice, without getting into details, we would prefer to wrap this call so as for return a real promise, or use some alternative to $.ajax that does so.) Now, if we want to load the file and wait for it to finish and then do something, we can simply say



                                                                                get_data() . then(do_something)


                                                                                for instance,



                                                                                get_data() . 
                                                                                then(function(data) { console.log(data); });


                                                                                When using promises, we end up passing lots of functions into then, so it's often helpful to use the more compact ES6-style arrow functions:



                                                                                get_data() . 
                                                                                then(data => console.log(data));


                                                                                The async keyword



                                                                                But there's still something vaguely dissatisfying about having to write code one way if synchronous and a quite different way if asynchronous. For synchronous, we write



                                                                                a();
                                                                                b();


                                                                                but if a is asynchronous, with promises we have to write



                                                                                a() . then(b);


                                                                                Above, we said, "JS has no way to know that it needs to wait for the first call to finish before it executes the second". Wouldn't it be nice if there was some way to tell JS that? It turns out that there is--the await keyword, used inside a special type of function called an "async" function. This feature is part of the upcoming version of ES but is already available in transpilers such as Babel given the right presets. This allows us to simply write



                                                                                async function morning_routine() {
                                                                                var milk = await order_milk();
                                                                                var coffee = await put_in_coffee(milk);
                                                                                await drink(coffee);
                                                                                }


                                                                                In your case, you would be able to write something like



                                                                                async function foo() {
                                                                                data = await get_data();
                                                                                console.log(data);
                                                                                }





                                                                                share|improve this answer



























                                                                                  up vote
                                                                                  18
                                                                                  down vote













                                                                                  We find ourselves in a universe which appears to progress along a dimension we call "time". We don't really understand what time is, but we have developed abstractions and vocabulary that let us reason and talk about it: "past", "present", "future", "before", "after".



                                                                                  The computer systems we build--more and more--have time as an important dimension. Certain things are set up to happen in the future. Then other things need to happen after those first things eventually occur. This is the basic notion called "asynchronicity". In our increasingly networked world, the most common case of asynchronicity is waiting for some remote system to respond to some request.



                                                                                  Consider an example. You call the milkman and order some milk. When it comes, you want to put it in your coffee. You can't put the milk in your coffee right now, because it is not here yet. You have to wait for it to come before putting it in your coffee. In other words, the following won't work:



                                                                                  var milk = order_milk();
                                                                                  put_in_coffee(milk);


                                                                                  Because JS has no way to know that it needs to wait for order_milk to finish before it executes put_in_coffee. In other words, it does not know that order_milk is asynchronous--is something that is not going to result in milk until some future time. JS, and other declarative languages execute one statement after another without waiting.



                                                                                  The classic JS approach to this problem, taking advantage of the fact that JS supports functions as first-class objects which can be passed around, is to pass a function as a parameter to the asynchronous request, which it will then invoke when it has completed its task sometime in the future. That is the "callback" approach. It looks like this:



                                                                                  order_milk(put_in_coffee);


                                                                                  order_milk kicks off, orders the milk, then, when and only when it arrives, it invokes put_in_coffee.



                                                                                  The problem with this callback approach is that it pollutes the normal semantics of a function reporting its result with return; instead, functions must not reports their results by calling a callback given as a parameter. Also, this approach can rapidly become unwieldy when dealing with longer sequences of events. For example, let's say that I want to wait for the milk to be put in the coffee, and then and only then perform a third step, namely drinking the coffee. I end up needing to write something like this:



                                                                                  order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }


                                                                                  where I am passing to put_in_coffee both the milk to put in it, and also the action (drink_coffee) to execute once the milk has been put in. Such code becomes hard to write, and read, and debug.



                                                                                  In this case, we could rewrite the code in the question as:



                                                                                  var answer;
                                                                                  $.ajax('/foo.json') . done(function(response) {
                                                                                  callback(response.data);
                                                                                  });

                                                                                  function callback(data) {
                                                                                  console.log(data);
                                                                                  }


                                                                                  Enter promises



                                                                                  This was the motivation for the notion of a "promise", which is a particular type of value which represents a future or asynchronous outcome of some sort. It can represent something that already happened, or that is going to happen in the future, or might never happen at all. Promises have a single method, named then, to which you pass an action to be executed when the outcome the promise represents has been realized.



                                                                                  In the case of our milk and coffee, we design order_milk to return a promise for the milk arriving, then specify put_in_coffee as a then action, as follows:



                                                                                  order_milk() . then(put_in_coffee)


                                                                                  One advantage of this is that we can string these together to create sequences of future occurrences ("chaining"):



                                                                                  order_milk() . then(put_in_coffee) . then(drink_coffee)


                                                                                  Let's apply promises to your particular problem. We will wrap our request logic inside a function, which returns a promise:



                                                                                  function get_data() {
                                                                                  return $.ajax('/foo.json');
                                                                                  }


                                                                                  Actually, all we've done is added a return to the call to $.ajax. This works because jQuery's $.ajax already returns a kind of promise-like thing. (In practice, without getting into details, we would prefer to wrap this call so as for return a real promise, or use some alternative to $.ajax that does so.) Now, if we want to load the file and wait for it to finish and then do something, we can simply say



                                                                                  get_data() . then(do_something)


                                                                                  for instance,



                                                                                  get_data() . 
                                                                                  then(function(data) { console.log(data); });


                                                                                  When using promises, we end up passing lots of functions into then, so it's often helpful to use the more compact ES6-style arrow functions:



                                                                                  get_data() . 
                                                                                  then(data => console.log(data));


                                                                                  The async keyword



                                                                                  But there's still something vaguely dissatisfying about having to write code one way if synchronous and a quite different way if asynchronous. For synchronous, we write



                                                                                  a();
                                                                                  b();


                                                                                  but if a is asynchronous, with promises we have to write



                                                                                  a() . then(b);


                                                                                  Above, we said, "JS has no way to know that it needs to wait for the first call to finish before it executes the second". Wouldn't it be nice if there was some way to tell JS that? It turns out that there is--the await keyword, used inside a special type of function called an "async" function. This feature is part of the upcoming version of ES but is already available in transpilers such as Babel given the right presets. This allows us to simply write



                                                                                  async function morning_routine() {
                                                                                  var milk = await order_milk();
                                                                                  var coffee = await put_in_coffee(milk);
                                                                                  await drink(coffee);
                                                                                  }


                                                                                  In your case, you would be able to write something like



                                                                                  async function foo() {
                                                                                  data = await get_data();
                                                                                  console.log(data);
                                                                                  }





                                                                                  share|improve this answer

























                                                                                    up vote
                                                                                    18
                                                                                    down vote










                                                                                    up vote
                                                                                    18
                                                                                    down vote









                                                                                    We find ourselves in a universe which appears to progress along a dimension we call "time". We don't really understand what time is, but we have developed abstractions and vocabulary that let us reason and talk about it: "past", "present", "future", "before", "after".



                                                                                    The computer systems we build--more and more--have time as an important dimension. Certain things are set up to happen in the future. Then other things need to happen after those first things eventually occur. This is the basic notion called "asynchronicity". In our increasingly networked world, the most common case of asynchronicity is waiting for some remote system to respond to some request.



                                                                                    Consider an example. You call the milkman and order some milk. When it comes, you want to put it in your coffee. You can't put the milk in your coffee right now, because it is not here yet. You have to wait for it to come before putting it in your coffee. In other words, the following won't work:



                                                                                    var milk = order_milk();
                                                                                    put_in_coffee(milk);


                                                                                    Because JS has no way to know that it needs to wait for order_milk to finish before it executes put_in_coffee. In other words, it does not know that order_milk is asynchronous--is something that is not going to result in milk until some future time. JS, and other declarative languages execute one statement after another without waiting.



                                                                                    The classic JS approach to this problem, taking advantage of the fact that JS supports functions as first-class objects which can be passed around, is to pass a function as a parameter to the asynchronous request, which it will then invoke when it has completed its task sometime in the future. That is the "callback" approach. It looks like this:



                                                                                    order_milk(put_in_coffee);


                                                                                    order_milk kicks off, orders the milk, then, when and only when it arrives, it invokes put_in_coffee.



                                                                                    The problem with this callback approach is that it pollutes the normal semantics of a function reporting its result with return; instead, functions must not reports their results by calling a callback given as a parameter. Also, this approach can rapidly become unwieldy when dealing with longer sequences of events. For example, let's say that I want to wait for the milk to be put in the coffee, and then and only then perform a third step, namely drinking the coffee. I end up needing to write something like this:



                                                                                    order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }


                                                                                    where I am passing to put_in_coffee both the milk to put in it, and also the action (drink_coffee) to execute once the milk has been put in. Such code becomes hard to write, and read, and debug.



                                                                                    In this case, we could rewrite the code in the question as:



                                                                                    var answer;
                                                                                    $.ajax('/foo.json') . done(function(response) {
                                                                                    callback(response.data);
                                                                                    });

                                                                                    function callback(data) {
                                                                                    console.log(data);
                                                                                    }


                                                                                    Enter promises



                                                                                    This was the motivation for the notion of a "promise", which is a particular type of value which represents a future or asynchronous outcome of some sort. It can represent something that already happened, or that is going to happen in the future, or might never happen at all. Promises have a single method, named then, to which you pass an action to be executed when the outcome the promise represents has been realized.



                                                                                    In the case of our milk and coffee, we design order_milk to return a promise for the milk arriving, then specify put_in_coffee as a then action, as follows:



                                                                                    order_milk() . then(put_in_coffee)


                                                                                    One advantage of this is that we can string these together to create sequences of future occurrences ("chaining"):



                                                                                    order_milk() . then(put_in_coffee) . then(drink_coffee)


                                                                                    Let's apply promises to your particular problem. We will wrap our request logic inside a function, which returns a promise:



                                                                                    function get_data() {
                                                                                    return $.ajax('/foo.json');
                                                                                    }


                                                                                    Actually, all we've done is added a return to the call to $.ajax. This works because jQuery's $.ajax already returns a kind of promise-like thing. (In practice, without getting into details, we would prefer to wrap this call so as for return a real promise, or use some alternative to $.ajax that does so.) Now, if we want to load the file and wait for it to finish and then do something, we can simply say



                                                                                    get_data() . then(do_something)


                                                                                    for instance,



                                                                                    get_data() . 
                                                                                    then(function(data) { console.log(data); });


                                                                                    When using promises, we end up passing lots of functions into then, so it's often helpful to use the more compact ES6-style arrow functions:



                                                                                    get_data() . 
                                                                                    then(data => console.log(data));


                                                                                    The async keyword



                                                                                    But there's still something vaguely dissatisfying about having to write code one way if synchronous and a quite different way if asynchronous. For synchronous, we write



                                                                                    a();
                                                                                    b();


                                                                                    but if a is asynchronous, with promises we have to write



                                                                                    a() . then(b);


                                                                                    Above, we said, "JS has no way to know that it needs to wait for the first call to finish before it executes the second". Wouldn't it be nice if there was some way to tell JS that? It turns out that there is--the await keyword, used inside a special type of function called an "async" function. This feature is part of the upcoming version of ES but is already available in transpilers such as Babel given the right presets. This allows us to simply write



                                                                                    async function morning_routine() {
                                                                                    var milk = await order_milk();
                                                                                    var coffee = await put_in_coffee(milk);
                                                                                    await drink(coffee);
                                                                                    }


                                                                                    In your case, you would be able to write something like



                                                                                    async function foo() {
                                                                                    data = await get_data();
                                                                                    console.log(data);
                                                                                    }





                                                                                    share|improve this answer














                                                                                    We find ourselves in a universe which appears to progress along a dimension we call "time". We don't really understand what time is, but we have developed abstractions and vocabulary that let us reason and talk about it: "past", "present", "future", "before", "after".



                                                                                    The computer systems we build--more and more--have time as an important dimension. Certain things are set up to happen in the future. Then other things need to happen after those first things eventually occur. This is the basic notion called "asynchronicity". In our increasingly networked world, the most common case of asynchronicity is waiting for some remote system to respond to some request.



                                                                                    Consider an example. You call the milkman and order some milk. When it comes, you want to put it in your coffee. You can't put the milk in your coffee right now, because it is not here yet. You have to wait for it to come before putting it in your coffee. In other words, the following won't work:



                                                                                    var milk = order_milk();
                                                                                    put_in_coffee(milk);


                                                                                    Because JS has no way to know that it needs to wait for order_milk to finish before it executes put_in_coffee. In other words, it does not know that order_milk is asynchronous--is something that is not going to result in milk until some future time. JS, and other declarative languages execute one statement after another without waiting.



                                                                                    The classic JS approach to this problem, taking advantage of the fact that JS supports functions as first-class objects which can be passed around, is to pass a function as a parameter to the asynchronous request, which it will then invoke when it has completed its task sometime in the future. That is the "callback" approach. It looks like this:



                                                                                    order_milk(put_in_coffee);


                                                                                    order_milk kicks off, orders the milk, then, when and only when it arrives, it invokes put_in_coffee.



                                                                                    The problem with this callback approach is that it pollutes the normal semantics of a function reporting its result with return; instead, functions must not reports their results by calling a callback given as a parameter. Also, this approach can rapidly become unwieldy when dealing with longer sequences of events. For example, let's say that I want to wait for the milk to be put in the coffee, and then and only then perform a third step, namely drinking the coffee. I end up needing to write something like this:



                                                                                    order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }


                                                                                    where I am passing to put_in_coffee both the milk to put in it, and also the action (drink_coffee) to execute once the milk has been put in. Such code becomes hard to write, and read, and debug.



                                                                                    In this case, we could rewrite the code in the question as:



                                                                                    var answer;
                                                                                    $.ajax('/foo.json') . done(function(response) {
                                                                                    callback(response.data);
                                                                                    });

                                                                                    function callback(data) {
                                                                                    console.log(data);
                                                                                    }


                                                                                    Enter promises



                                                                                    This was the motivation for the notion of a "promise", which is a particular type of value which represents a future or asynchronous outcome of some sort. It can represent something that already happened, or that is going to happen in the future, or might never happen at all. Promises have a single method, named then, to which you pass an action to be executed when the outcome the promise represents has been realized.



                                                                                    In the case of our milk and coffee, we design order_milk to return a promise for the milk arriving, then specify put_in_coffee as a then action, as follows:



                                                                                    order_milk() . then(put_in_coffee)


                                                                                    One advantage of this is that we can string these together to create sequences of future occurrences ("chaining"):



                                                                                    order_milk() . then(put_in_coffee) . then(drink_coffee)


                                                                                    Let's apply promises to your particular problem. We will wrap our request logic inside a function, which returns a promise:



                                                                                    function get_data() {
                                                                                    return $.ajax('/foo.json');
                                                                                    }


                                                                                    Actually, all we've done is added a return to the call to $.ajax. This works because jQuery's $.ajax already returns a kind of promise-like thing. (In practice, without getting into details, we would prefer to wrap this call so as for return a real promise, or use some alternative to $.ajax that does so.) Now, if we want to load the file and wait for it to finish and then do something, we can simply say



                                                                                    get_data() . then(do_something)


                                                                                    for instance,



                                                                                    get_data() . 
                                                                                    then(function(data) { console.log(data); });


                                                                                    When using promises, we end up passing lots of functions into then, so it's often helpful to use the more compact ES6-style arrow functions:



                                                                                    get_data() . 
                                                                                    then(data => console.log(data));


                                                                                    The async keyword



                                                                                    But there's still something vaguely dissatisfying about having to write code one way if synchronous and a quite different way if asynchronous. For synchronous, we write



                                                                                    a();
                                                                                    b();


                                                                                    but if a is asynchronous, with promises we have to write



                                                                                    a() . then(b);


                                                                                    Above, we said, "JS has no way to know that it needs to wait for the first call to finish before it executes the second". Wouldn't it be nice if there was some way to tell JS that? It turns out that there is--the await keyword, used inside a special type of function called an "async" function. This feature is part of the upcoming version of ES but is already available in transpilers such as Babel given the right presets. This allows us to simply write



                                                                                    async function morning_routine() {
                                                                                    var milk = await order_milk();
                                                                                    var coffee = await put_in_coffee(milk);
                                                                                    await drink(coffee);
                                                                                    }


                                                                                    In your case, you would be able to write something like



                                                                                    async function foo() {
                                                                                    data = await get_data();
                                                                                    console.log(data);
                                                                                    }






                                                                                    share|improve this answer














                                                                                    share|improve this answer



                                                                                    share|improve this answer








                                                                                    edited Dec 10 at 5:52


























                                                                                    community wiki





                                                                                    4 revs, 3 users 92%
                                                                                    user663031























                                                                                        up vote
                                                                                        11
                                                                                        down vote













                                                                                        Using ES2017 you should have this as the function declaration



                                                                                        async function foo() {
                                                                                        var response = await $.ajax({url: '...'})
                                                                                        return response;
                                                                                        }


                                                                                        And executing it like this.



                                                                                        (async function() {
                                                                                        try {
                                                                                        var result = await foo()
                                                                                        console.log(result)
                                                                                        } catch (e) {}
                                                                                        })()


                                                                                        Or the Promise syntax



                                                                                        foo().then(response => {
                                                                                        console.log(response)

                                                                                        }).catch(error => {
                                                                                        console.log(error)

                                                                                        })





                                                                                        share|improve this answer

























                                                                                          up vote
                                                                                          11
                                                                                          down vote













                                                                                          Using ES2017 you should have this as the function declaration



                                                                                          async function foo() {
                                                                                          var response = await $.ajax({url: '...'})
                                                                                          return response;
                                                                                          }


                                                                                          And executing it like this.



                                                                                          (async function() {
                                                                                          try {
                                                                                          var result = await foo()
                                                                                          console.log(result)
                                                                                          } catch (e) {}
                                                                                          })()


                                                                                          Or the Promise syntax



                                                                                          foo().then(response => {
                                                                                          console.log(response)

                                                                                          }).catch(error => {
                                                                                          console.log(error)

                                                                                          })





                                                                                          share|improve this answer























                                                                                            up vote
                                                                                            11
                                                                                            down vote










                                                                                            up vote
                                                                                            11
                                                                                            down vote









                                                                                            Using ES2017 you should have this as the function declaration



                                                                                            async function foo() {
                                                                                            var response = await $.ajax({url: '...'})
                                                                                            return response;
                                                                                            }


                                                                                            And executing it like this.



                                                                                            (async function() {
                                                                                            try {
                                                                                            var result = await foo()
                                                                                            console.log(result)
                                                                                            } catch (e) {}
                                                                                            })()


                                                                                            Or the Promise syntax



                                                                                            foo().then(response => {
                                                                                            console.log(response)

                                                                                            }).catch(error => {
                                                                                            console.log(error)

                                                                                            })





                                                                                            share|improve this answer












                                                                                            Using ES2017 you should have this as the function declaration



                                                                                            async function foo() {
                                                                                            var response = await $.ajax({url: '...'})
                                                                                            return response;
                                                                                            }


                                                                                            And executing it like this.



                                                                                            (async function() {
                                                                                            try {
                                                                                            var result = await foo()
                                                                                            console.log(result)
                                                                                            } catch (e) {}
                                                                                            })()


                                                                                            Or the Promise syntax



                                                                                            foo().then(response => {
                                                                                            console.log(response)

                                                                                            }).catch(error => {
                                                                                            console.log(error)

                                                                                            })






                                                                                            share|improve this answer












                                                                                            share|improve this answer



                                                                                            share|improve this answer










                                                                                            answered Jan 24 at 6:18









                                                                                            Fernando Carvajal

                                                                                            599513




                                                                                            599513






















                                                                                                up vote
                                                                                                10
                                                                                                down vote













                                                                                                Let's see the forest first before looking at the trees.



                                                                                                There are many informative answers with great details here, I won't repeat any of them. The key to programming in JavaScript is having first the correct mental model of overall execution.




                                                                                                1. Your entry point(s) is executed as the result of an event. For
                                                                                                  example, a script tag with code is loaded into the browser.
                                                                                                  (Accordingly, this is why you may need to be concerned with the
                                                                                                  readiness of the page to run your code if it requires dom elements
                                                                                                  to be constructed first, etc.)

                                                                                                2. Your code executes to completion--however many asynchronous calls it
                                                                                                  makes--without executing any of your callbacks, including XHR
                                                                                                  requests, set timeouts, dom event handlers, etc. Each of those callbacks waiting to be executed will sit in a queue, waiting their turn to be run after other events that fired have all finished execution.

                                                                                                3. Each individual callback to an XHR request, set timeout or dom
                                                                                                  the event once invoked will then run to completion.


                                                                                                The good news is that if you understand this point well, you will never have to worry about race conditions. You should first and foremost thing of how you want to organize your code as essentially the response to different discrete events, and how you want to thread them together into a logical sequence. You can use promises or higher level new async/await as tools to that end, or you can roll your own.



                                                                                                But you shouldn't use any tactical tools to solve a problem until you are comfortable with the actual problem domain. Draw a map of these dependencies to know what needs to run when. Attempting an ad-hoc approach to all these callbacks is just not going to serve you well.






                                                                                                share|improve this answer



























                                                                                                  up vote
                                                                                                  10
                                                                                                  down vote













                                                                                                  Let's see the forest first before looking at the trees.



                                                                                                  There are many informative answers with great details here, I won't repeat any of them. The key to programming in JavaScript is having first the correct mental model of overall execution.




                                                                                                  1. Your entry point(s) is executed as the result of an event. For
                                                                                                    example, a script tag with code is loaded into the browser.
                                                                                                    (Accordingly, this is why you may need to be concerned with the
                                                                                                    readiness of the page to run your code if it requires dom elements
                                                                                                    to be constructed first, etc.)

                                                                                                  2. Your code executes to completion--however many asynchronous calls it
                                                                                                    makes--without executing any of your callbacks, including XHR
                                                                                                    requests, set timeouts, dom event handlers, etc. Each of those callbacks waiting to be executed will sit in a queue, waiting their turn to be run after other events that fired have all finished execution.

                                                                                                  3. Each individual callback to an XHR request, set timeout or dom
                                                                                                    the event once invoked will then run to completion.


                                                                                                  The good news is that if you understand this point well, you will never have to worry about race conditions. You should first and foremost thing of how you want to organize your code as essentially the response to different discrete events, and how you want to thread them together into a logical sequence. You can use promises or higher level new async/await as tools to that end, or you can roll your own.



                                                                                                  But you shouldn't use any tactical tools to solve a problem until you are comfortable with the actual problem domain. Draw a map of these dependencies to know what needs to run when. Attempting an ad-hoc approach to all these callbacks is just not going to serve you well.






                                                                                                  share|improve this answer

























                                                                                                    up vote
                                                                                                    10
                                                                                                    down vote










                                                                                                    up vote
                                                                                                    10
                                                                                                    down vote









                                                                                                    Let's see the forest first before looking at the trees.



                                                                                                    There are many informative answers with great details here, I won't repeat any of them. The key to programming in JavaScript is having first the correct mental model of overall execution.




                                                                                                    1. Your entry point(s) is executed as the result of an event. For
                                                                                                      example, a script tag with code is loaded into the browser.
                                                                                                      (Accordingly, this is why you may need to be concerned with the
                                                                                                      readiness of the page to run your code if it requires dom elements
                                                                                                      to be constructed first, etc.)

                                                                                                    2. Your code executes to completion--however many asynchronous calls it
                                                                                                      makes--without executing any of your callbacks, including XHR
                                                                                                      requests, set timeouts, dom event handlers, etc. Each of those callbacks waiting to be executed will sit in a queue, waiting their turn to be run after other events that fired have all finished execution.

                                                                                                    3. Each individual callback to an XHR request, set timeout or dom
                                                                                                      the event once invoked will then run to completion.


                                                                                                    The good news is that if you understand this point well, you will never have to worry about race conditions. You should first and foremost thing of how you want to organize your code as essentially the response to different discrete events, and how you want to thread them together into a logical sequence. You can use promises or higher level new async/await as tools to that end, or you can roll your own.



                                                                                                    But you shouldn't use any tactical tools to solve a problem until you are comfortable with the actual problem domain. Draw a map of these dependencies to know what needs to run when. Attempting an ad-hoc approach to all these callbacks is just not going to serve you well.






                                                                                                    share|improve this answer














                                                                                                    Let's see the forest first before looking at the trees.



                                                                                                    There are many informative answers with great details here, I won't repeat any of them. The key to programming in JavaScript is having first the correct mental model of overall execution.




                                                                                                    1. Your entry point(s) is executed as the result of an event. For
                                                                                                      example, a script tag with code is loaded into the browser.
                                                                                                      (Accordingly, this is why you may need to be concerned with the
                                                                                                      readiness of the page to run your code if it requires dom elements
                                                                                                      to be constructed first, etc.)

                                                                                                    2. Your code executes to completion--however many asynchronous calls it
                                                                                                      makes--without executing any of your callbacks, including XHR
                                                                                                      requests, set timeouts, dom event handlers, etc. Each of those callbacks waiting to be executed will sit in a queue, waiting their turn to be run after other events that fired have all finished execution.

                                                                                                    3. Each individual callback to an XHR request, set timeout or dom
                                                                                                      the event once invoked will then run to completion.


                                                                                                    The good news is that if you understand this point well, you will never have to worry about race conditions. You should first and foremost thing of how you want to organize your code as essentially the response to different discrete events, and how you want to thread them together into a logical sequence. You can use promises or higher level new async/await as tools to that end, or you can roll your own.



                                                                                                    But you shouldn't use any tactical tools to solve a problem until you are comfortable with the actual problem domain. Draw a map of these dependencies to know what needs to run when. Attempting an ad-hoc approach to all these callbacks is just not going to serve you well.







                                                                                                    share|improve this answer














                                                                                                    share|improve this answer



                                                                                                    share|improve this answer








                                                                                                    edited Oct 29 '17 at 8:36









                                                                                                    eFarzad

                                                                                                    559721




                                                                                                    559721










                                                                                                    answered Oct 25 '17 at 3:22









                                                                                                    Haim Zamir

                                                                                                    17414




                                                                                                    17414






















                                                                                                        up vote
                                                                                                        9
                                                                                                        down vote













                                                                                                        Rather than throwing code at you, there are 2 concepts that are key to understanding how JS handles callbacks and asynchronicity. (is that even a word?)



                                                                                                        The Event Loop and Concurrency Model



                                                                                                        There are three things you need to be aware of; The queue; the event loop and the stack



                                                                                                        In broad, simplistic terms, the event loop is like the project manager, it is constantly listening for any functions that want to run and communicates between the queue and the stack.



                                                                                                        while (queue.waitForMessage()) {
                                                                                                        queue.processNextMessage();
                                                                                                        }


                                                                                                        Once it receives a message to run something it adds it to the queue. The queue is the list of things that are waiting to execute (like your AJAX request). imagine it like this:



                                                                                                         1. call foo.com/api/bar using foobarFunc
                                                                                                        2. Go perform an infinite loop
                                                                                                        ... and so on


                                                                                                        When one of these messages is going to execute it pops the message from the queue and creates a stack, the stack is everything JS needs to execute to perform the instruction in the message. So in our example it's being told to call foobarFunc



                                                                                                        function foobarFunc (var) {
                                                                                                        console.log(anotherFunction(var));
                                                                                                        }


                                                                                                        So anything that foobarFunc needs to execute (in our case anotherFunction) will get pushed onto the stack. executed, and then forgotten about - the event loop will then move onto the next thing in the queue (or listen for messages)



                                                                                                        The key thing here is the order of execution. That is



                                                                                                        WHEN is something going to run



                                                                                                        When you make a call using AJAX to an external party or run any asynchronous code (a setTimeout for example), Javascript is dependant upon a response before it can proceed.



                                                                                                        The big question is when will it get the response? The answer is we don't know - so the event loop is waiting for that message to say "hey run me". If JS just waited around for that message synchronously your app would freeze and it will suck. So JS carries on executing the next item in the queue whilst waiting for the message to get added back to the queue.



                                                                                                        That's why with asynchronous functionality we use things called callbacks. It's kinda like a promise quite literally. As in I promise to return something at some point jQuery uses specific callbacks called deffered.done deffered.fail and deffered.always (amongst others). You can see them all here



                                                                                                        So what you need to do is pass a function that is promised to execute at some point with data that is passed to it.



                                                                                                        Because a callback is not executed immediately but at a later time it's important to pass the reference to the function not it executed. so



                                                                                                        function foo(bla) {
                                                                                                        console.log(bla)
                                                                                                        }


                                                                                                        so most of the time (but not always) you'll pass foo not foo()



                                                                                                        Hopefully that will make some sense. When you encounter things like this that seem confusing - i highly recommend reading the documentation fully to at least get an understanding of it. It will make you a much better developer.






                                                                                                        share|improve this answer

























                                                                                                          up vote
                                                                                                          9
                                                                                                          down vote













                                                                                                          Rather than throwing code at you, there are 2 concepts that are key to understanding how JS handles callbacks and asynchronicity. (is that even a word?)



                                                                                                          The Event Loop and Concurrency Model



                                                                                                          There are three things you need to be aware of; The queue; the event loop and the stack



                                                                                                          In broad, simplistic terms, the event loop is like the project manager, it is constantly listening for any functions that want to run and communicates between the queue and the stack.



                                                                                                          while (queue.waitForMessage()) {
                                                                                                          queue.processNextMessage();
                                                                                                          }


                                                                                                          Once it receives a message to run something it adds it to the queue. The queue is the list of things that are waiting to execute (like your AJAX request). imagine it like this:



                                                                                                           1. call foo.com/api/bar using foobarFunc
                                                                                                          2. Go perform an infinite loop
                                                                                                          ... and so on


                                                                                                          When one of these messages is going to execute it pops the message from the queue and creates a stack, the stack is everything JS needs to execute to perform the instruction in the message. So in our example it's being told to call foobarFunc



                                                                                                          function foobarFunc (var) {
                                                                                                          console.log(anotherFunction(var));
                                                                                                          }


                                                                                                          So anything that foobarFunc needs to execute (in our case anotherFunction) will get pushed onto the stack. executed, and then forgotten about - the event loop will then move onto the next thing in the queue (or listen for messages)



                                                                                                          The key thing here is the order of execution. That is



                                                                                                          WHEN is something going to run



                                                                                                          When you make a call using AJAX to an external party or run any asynchronous code (a setTimeout for example), Javascript is dependant upon a response before it can proceed.



                                                                                                          The big question is when will it get the response? The answer is we don't know - so the event loop is waiting for that message to say "hey run me". If JS just waited around for that message synchronously your app would freeze and it will suck. So JS carries on executing the next item in the queue whilst waiting for the message to get added back to the queue.



                                                                                                          That's why with asynchronous functionality we use things called callbacks. It's kinda like a promise quite literally. As in I promise to return something at some point jQuery uses specific callbacks called deffered.done deffered.fail and deffered.always (amongst others). You can see them all here



                                                                                                          So what you need to do is pass a function that is promised to execute at some point with data that is passed to it.



                                                                                                          Because a callback is not executed immediately but at a later time it's important to pass the reference to the function not it executed. so



                                                                                                          function foo(bla) {
                                                                                                          console.log(bla)
                                                                                                          }


                                                                                                          so most of the time (but not always) you'll pass foo not foo()



                                                                                                          Hopefully that will make some sense. When you encounter things like this that seem confusing - i highly recommend reading the documentation fully to at least get an understanding of it. It will make you a much better developer.






                                                                                                          share|improve this answer























                                                                                                            up vote
                                                                                                            9
                                                                                                            down vote










                                                                                                            up vote
                                                                                                            9
                                                                                                            down vote









                                                                                                            Rather than throwing code at you, there are 2 concepts that are key to understanding how JS handles callbacks and asynchronicity. (is that even a word?)



                                                                                                            The Event Loop and Concurrency Model



                                                                                                            There are three things you need to be aware of; The queue; the event loop and the stack



                                                                                                            In broad, simplistic terms, the event loop is like the project manager, it is constantly listening for any functions that want to run and communicates between the queue and the stack.



                                                                                                            while (queue.waitForMessage()) {
                                                                                                            queue.processNextMessage();
                                                                                                            }


                                                                                                            Once it receives a message to run something it adds it to the queue. The queue is the list of things that are waiting to execute (like your AJAX request). imagine it like this:



                                                                                                             1. call foo.com/api/bar using foobarFunc
                                                                                                            2. Go perform an infinite loop
                                                                                                            ... and so on


                                                                                                            When one of these messages is going to execute it pops the message from the queue and creates a stack, the stack is everything JS needs to execute to perform the instruction in the message. So in our example it's being told to call foobarFunc



                                                                                                            function foobarFunc (var) {
                                                                                                            console.log(anotherFunction(var));
                                                                                                            }


                                                                                                            So anything that foobarFunc needs to execute (in our case anotherFunction) will get pushed onto the stack. executed, and then forgotten about - the event loop will then move onto the next thing in the queue (or listen for messages)



                                                                                                            The key thing here is the order of execution. That is



                                                                                                            WHEN is something going to run



                                                                                                            When you make a call using AJAX to an external party or run any asynchronous code (a setTimeout for example), Javascript is dependant upon a response before it can proceed.



                                                                                                            The big question is when will it get the response? The answer is we don't know - so the event loop is waiting for that message to say "hey run me". If JS just waited around for that message synchronously your app would freeze and it will suck. So JS carries on executing the next item in the queue whilst waiting for the message to get added back to the queue.



                                                                                                            That's why with asynchronous functionality we use things called callbacks. It's kinda like a promise quite literally. As in I promise to return something at some point jQuery uses specific callbacks called deffered.done deffered.fail and deffered.always (amongst others). You can see them all here



                                                                                                            So what you need to do is pass a function that is promised to execute at some point with data that is passed to it.



                                                                                                            Because a callback is not executed immediately but at a later time it's important to pass the reference to the function not it executed. so



                                                                                                            function foo(bla) {
                                                                                                            console.log(bla)
                                                                                                            }


                                                                                                            so most of the time (but not always) you'll pass foo not foo()



                                                                                                            Hopefully that will make some sense. When you encounter things like this that seem confusing - i highly recommend reading the documentation fully to at least get an understanding of it. It will make you a much better developer.






                                                                                                            share|improve this answer












                                                                                                            Rather than throwing code at you, there are 2 concepts that are key to understanding how JS handles callbacks and asynchronicity. (is that even a word?)



                                                                                                            The Event Loop and Concurrency Model



                                                                                                            There are three things you need to be aware of; The queue; the event loop and the stack



                                                                                                            In broad, simplistic terms, the event loop is like the project manager, it is constantly listening for any functions that want to run and communicates between the queue and the stack.



                                                                                                            while (queue.waitForMessage()) {
                                                                                                            queue.processNextMessage();
                                                                                                            }


                                                                                                            Once it receives a message to run something it adds it to the queue. The queue is the list of things that are waiting to execute (like your AJAX request). imagine it like this:



                                                                                                             1. call foo.com/api/bar using foobarFunc
                                                                                                            2. Go perform an infinite loop
                                                                                                            ... and so on


                                                                                                            When one of these messages is going to execute it pops the message from the queue and creates a stack, the stack is everything JS needs to execute to perform the instruction in the message. So in our example it's being told to call foobarFunc



                                                                                                            function foobarFunc (var) {
                                                                                                            console.log(anotherFunction(var));
                                                                                                            }


                                                                                                            So anything that foobarFunc needs to execute (in our case anotherFunction) will get pushed onto the stack. executed, and then forgotten about - the event loop will then move onto the next thing in the queue (or listen for messages)



                                                                                                            The key thing here is the order of execution. That is



                                                                                                            WHEN is something going to run



                                                                                                            When you make a call using AJAX to an external party or run any asynchronous code (a setTimeout for example), Javascript is dependant upon a response before it can proceed.



                                                                                                            The big question is when will it get the response? The answer is we don't know - so the event loop is waiting for that message to say "hey run me". If JS just waited around for that message synchronously your app would freeze and it will suck. So JS carries on executing the next item in the queue whilst waiting for the message to get added back to the queue.



                                                                                                            That's why with asynchronous functionality we use things called callbacks. It's kinda like a promise quite literally. As in I promise to return something at some point jQuery uses specific callbacks called deffered.done deffered.fail and deffered.always (amongst others). You can see them all here



                                                                                                            So what you need to do is pass a function that is promised to execute at some point with data that is passed to it.



                                                                                                            Because a callback is not executed immediately but at a later time it's important to pass the reference to the function not it executed. so



                                                                                                            function foo(bla) {
                                                                                                            console.log(bla)
                                                                                                            }


                                                                                                            so most of the time (but not always) you'll pass foo not foo()



                                                                                                            Hopefully that will make some sense. When you encounter things like this that seem confusing - i highly recommend reading the documentation fully to at least get an understanding of it. It will make you a much better developer.







                                                                                                            share|improve this answer












                                                                                                            share|improve this answer



                                                                                                            share|improve this answer










                                                                                                            answered May 4 at 15:56









                                                                                                            Matthew Brent

                                                                                                            774518




                                                                                                            774518






















                                                                                                                1 2
                                                                                                                next




                                                                                                                protected by Travis J May 30 '13 at 20:57



                                                                                                                Thank you for your interest in this question.
                                                                                                                Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                                                                                Would you like to answer one of these unanswered questions instead?



                                                                                                                Popular posts from this blog

                                                                                                                Berounka

                                                                                                                Fiat S.p.A.

                                                                                                                Type 'String' is not a subtype of type 'int' of 'index'