Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h1>If you're <em>not</em> using jQuery in your code, this answer is for you</h1> <p>Your code should be something along the lines of this:</p> <pre><code>function foo() { var httpRequest = new XMLHttpRequest(); httpRequest.open('GET', "/echo/json"); httpRequest.send(); return httpRequest.responseText; } var result = foo(); // always ends up being 'undefined' </code></pre> <p>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.</p> <p>(<a href="https://stackoverflow.com/a/30180679/1348195">Note, for those using the new <code>fetch</code> API, Angular or promises I've added another answer below</a>)</p> <hr> <h1>What you're facing</h1> <p>This is a short summary of "Explanation of the problem" from the other answer, if you're not sure after reading this, read that.</p> <p>The <strong>A</strong> in AJAX stands for <strong>asynchronous</strong>. That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#send%28%29" rel="noreferrer"><code>.send</code></a> returns immediately and the next statement, <code>return result;</code>, is executed before the function you passed as <code>success</code> callback was even called.</p> <p>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. </p> <p>Here is a simple analogy</p> <pre><code>function getFive(){ var a; setTimeout(function(){ a=5; },10); return a; } </code></pre> <p><a href="http://jsfiddle.net/7RK3k/" rel="noreferrer">(Fiddle)</a></p> <p>The value of <code>a</code> returned is <code>undefined</code> since the <code>a=5</code> 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.</p> <p>One possible solution to this problem is to code <em>re-actively</em> , telling your program what to do when the calculation completed.</p> <pre><code>function onComplete(a){ // When the code completes, do this alert(a); } function getFive(whenDone){ var a; setTimeout(function(){ a=5; whenDone(a); },10); } </code></pre> <p>This is called <a href="http://en.wikipedia.org/wiki/Continuation-passing_style" rel="noreferrer">CPS</a>. Basically, we're passing <code>getFive</code> 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).</p> <p>Usage would be:</p> <pre><code>getFive(onComplete); </code></pre> <p>Which should alert "5" to the screen. <a href="http://jsfiddle.net/PAjZR/" rel="noreferrer">(Fiddle)</a>.</p> <h1>Possible solutions</h1> <p>There are basically two ways how to solve this:</p> <ol> <li>Make the AJAX call synchronous (lets call it SJAX).</li> <li>Restructure your code to work properly with callbacks.</li> </ol> <h2>1. Synchronous AJAX - Don't do it!!</h2> <p>As for synchronous AJAX, <strong>don't do it!</strong> 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:</p> <blockquote> <p>XMLHttpRequest supports both synchronous and asynchronous communications. In general, however, asynchronous requests should be preferred to synchronous requests for performance reasons.</p> <p>In short, synchronous requests block the execution of code... ...this can cause serious issues...</p> </blockquote> <p>If you <em>have</em> to do it, you can pass a flag: <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests#Synchronous_request" rel="noreferrer">Here is how:</a></p> <pre><code>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); } </code></pre> <h2>2. Restructure code</h2> <p>Let your function accept a callback. In the example code <code>foo</code> can be made to accept a callback. We'll be telling our code how to <em>react</em> when <code>foo</code> completes. </p> <p>So:</p> <pre><code>var result = foo(); // code that depends on `result` goes here </code></pre> <p>Becomes:</p> <pre><code>foo(function(result) { // code that depends on `result` }); </code></pre> <p>Here we passed an anonymous function, but we could just as easily pass a reference to an existing function, making it look like:</p> <pre><code>function myHandler(result) { // code that depends on `result` } foo(myHandler); </code></pre> <p>For more details on how this sort of callback design is done, check Felix's answer. </p> <p>Now, let's define foo itself to act accordingly</p> <pre><code>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(); } </code></pre> <p><a href="http://jsfiddle.net/DAcWT/" rel="noreferrer">(fiddle)</a></p> <p>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.</p> <p>If you're still having a hard time understanding this <a href="https://developer.mozilla.org/en-US/docs/AJAX/Getting_Started" rel="noreferrer">read the AJAX getting started guide</a> at MDN.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload