← Learn Javascript

Asynchronous Javascript

How to use callbacks, fetch, promises, async/await, etc.

slides | md

Sync vs. Async

  • When getting data from the hard disk or network you will encounter latencyβ€”the amount of time it takes the data to arrive.
  • Asynchronous code ensures such operations (e.g. API responses) have completed before using the data of the response.
// synchronous code
function example1(num) {
	console.log("🐱", num);
}
example1(1);
console.log("🐱", 2);
What is the order? Left: 1,2; Right: 2,1
Also see Why do we need asynchronous code? (codepen)
// asynchronous code
function example2(num){
	setTimeout(function(){
		console.log("🐨", num);
	}, 1000);
}
example2(1);
console.log("🐨", 2);

Async code

Here are some ways you can deal with latency in Javascript:

  1. Event Handlers
  2. Callbacks
  3. Promises & Async/Await

Event Handlers

If you have used event listeners or jQuery then you are already know Event Handlers.

// vanilla JS
let btn = document.querySelector('button');
btn.addEventListener('click', () => {
	console.log("click!!");
});

// jQuery
$("button").click(function() {
	console.log("click!!");
});

Callbacks

  • A callback is a function that is passed to another function, to be called once the function is complete.
  • Callbacks were once the primary strategy for asynchronous code in JavaScript.
  • The jQuery function from the previous lesson can be written either way...
// callback function is embedded
$("button").click(function() {
	console.log("click!!");
});
// callback stored in variable
let callback = function() {
	console.log("click!!");
}
$("button").click(callback);

Callback Hell

Since callbacks require nesting functions, it makes your code difficult to manage.

let arr = []; // a rather extreme version of callback hell or "the pyramid of doom"
getUser(id1, function(user1){
	arr.push(user1.name);
	if (user1.friends.length > 0){
		getUser(user1.friends[0], function(user2){
			arr.push(user2.name);
			if (user2.friends.length > 0){
				getUser(user2.friends[0], function(user3){
					arr.push(user3.name); // and so on until done
				});
			}
		});
	}
});
getUser(1); // getting a list of connections

Promises

  • A JS promise lets you make asynchronous requests and use the result when a response is received.
  • A function (like fetch()) that returns a promise tells the calling function the request is in progress.
fetch('https://api.weather.gov/')
// -> Promise {<pending>}
// ->   [[Prototype]] : Promise 
// ->   [[PromiseState]] : "fulfilled"
// ->   [[PromiseResult]] : Response

Fetch

  • The data in the response from fetch() can be use in a promise chain where each .then() is performed in order.
  • Below, the response is converted to JSON object in the first then, and finally logged to the console in the 2nd.
fetch('https://jsonplaceholder.typicode.com/todos')
	.then(response => response.json())
	.then(json => {
		console.log(json);
	});

See: Why do we need asynchronous code?

Async/Await

  • Use async/await to wait for a promise to be fulfilled.
  • Below, await (inside async functions) causes the log statements to occur in order.
async function fetchFunction(){
    let jsonData;
    await fetch('https://jsonplaceholder.typicode.com/todos')
        .then(response => response.json())
        .then(json => { jsonData = json; });
    return jsonData;    
}
(async function(){ 
    console.log(123)
    let data = await fetchFunction();
    console.log(data);
    console.log(456)
})()

See: How to wrap fetch() in a function

Next steps

  1. Explore ./demos.
  2. Try the Exercises below.
  3. Start working on homework listed in the schedule.
  4. Continue to the next lesson.

Exercises

πŸ‘‰ Try it out

  1. Ch11 Tracking the scalpel, Building Promise.all

References

Resources

Presentation comments ...

FROM THE OLD REPO, NEED TO DELETE OR INTEGRATE ```js // callback example function log(answer) { console.log("The answer is " + answer); } function sum(n1, n2, callback) { // sum n1, n2 and invoke callback function callback(n1 + n2); } // pass a function as a callback sum(5, 5, log); // promise example function waitForPromise(param) { return new Promise(resolve => { setTimeout(() => { resolve(param); }, 2000); }); } // async function async function test() { let str = ""; // use await to wait for promise in synchronous code str += await waitForPromise("🀑"); console.log(str); str += await waitForPromise(" lurks"); console.log(str); str += await waitForPromise(" in the shadows"); console.log(str); } test(); ```