Quantcast
Viewing latest article 2
Browse Latest Browse All 44

Answer by Henke for How do I return the response from an asynchronous call?

1. A first stumbling step

As for many others, my encounter with asynchronous calls was puzzling at first.
I don't remember the details, but I may have tried something like:

let result;$.ajax({  url: 'https://jsonplaceholder.typicode.com/todos/1',  success: function (response) {    console.log('\nInside $.ajax:');    console.log(response);    result = response;  },});console.log('Finally, the result: '+ result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

Whoops!
The output of the lineconsole.log('Finally, the result: '+ result);which I thought would be printed last, is printed before the other output!
– And it doesn't contain the result: it just prints undefined. 1
How come?

A helpful insight

I distinctly remember my first aha (💡) moment about asynchronous calls.It was :

you actually don't want to get the data out of a callback; you want to get your data-needing action into the callback!2

This is true in the example above.

2. Plain JavaScript and a callback function

Luckily, it is possible to write code after the asynchronous call that deals with the response once it has completed.

One alternative is the use of a callback function in a continuation-passing style :3

const url = 'https://jsonplaceholder.typicode.com/todos/2';function asynchronousFunc(callback) {  const request = new XMLHttpRequest();  request.open('GET', url);  request.send();  request.onload = function () {    if (request.readyState === request.DONE) {      console.log('The request is done. Now calling back.');      callback(request.responseText);    }  };}asynchronousFunc(function (result) {  console.log('This is the start of the callback function. Result:');  console.log(result);  console.log('The callback function finishes on this line. THE END!');});console.log('LAST in the code, but executed FIRST!');
.as-console-wrapper { max-height: 100% !important; top: 0; }

Note how the function asynchronousFunc is void. It returns nothing.
asynchronousFunc is called with an anonymous callback function,
(asynchronousFunc(function (result) {...});).
This executes the desired actions on the result after the request has completed – when the responseText is available.

Running the above snippet shows how I will probably not want to write any code after the asynchronous call (such as the lineLAST in the code, but executed FIRST!).
Why?– Because such code will run before the asynchronous call delivers any response data.
Doing so is bound to cause confusion when comparing the code with the output.

3. Promise with .then()

The .then() construct was introduced in the ECMA-262 6th Edition in June 2015.
The code below is plain JavaScript, replacing the old-school XMLHttpRequest with Fetch. 4

fetch('https://api.chucknorris.io/jokes/random')  .then((response) => response.json())  .then((responseBody) => {    console.log('Using .then() :');    console.log(responseBody.value +'\n');  });
.as-console-wrapper { max-height: 100% !important; top: 0; }

4. Promise with async/await

The async/await construct was introduced in the ECMA-262 8th Edition in June 2017.

async function awaitAndReceivePromise() {  const responseBody = (    await fetch('https://api.quotable.io/quotes/random')  ).json();  console.log('Using async/await:');  const obj = (await responseBody)[0];  console.log('"'+ obj.content +'"–'+ obj.author +'\n');}awaitAndReceivePromise();
.as-console-wrapper { max-height: 100% !important; top: 0; }

A word of warning is warranted if you decide to go with the async/await construct.Note in the above snippet how await is needed in two places.
If forgotten in the first place, there will be no output at all.If forgotten in the second place, the only output will be Using async/await:– nothing else gets printed.
Forgetting the async prefix of the function is maybe the worst of all – you'll get a "SyntaxError"– and likely no hint about the missingasync keyword.


All the above examples succinctly convey how asynchronous calls may be used on toyish APIs. 5

References


1Expressed by the asker of the question as they all return undefined.

2Here is more on how asynchronous calls may be confusing at first.

3Like the X in AJAX, the name XMLHttpRequest is misleading –it can be used to retrieve any type of data, not just XML.
These days, the data format of Web APIs is ubiquitously JSON, not XML.

4Fetch returns a Promise.I was surprised to learn that neither XMLHttpRequest nor Fetch are part of the ECMAScript standard.The reason JavaScript can access them here is that the web browser provides them.
The Fetch Standard and the XMLHttpRequest Standard are both upheld by the Web Hypertext Application Technology Working Group which was formed in June 2004. \

5You might also be interested inHow can I fetch an array of URLs with Promise.all?.


Viewing latest article 2
Browse Latest Browse All 44

Trending Articles