Learn Javascript

Asynchronous Javascript

Using callbacks, fetch, promises, async/await, etc.

slides | md

Sync vs. Async

Latency describes the time it takes to retrieve data across the web.

Synchronous code runs in succession, after previous lines have finished.

console.log(1, "These will...");
console.log(2, "execute");
console.log(3, "in order");
// -> 1 These will...
// -> 2 execute
// -> 3 in order

Asynchronous code can handle requests that depend on data from the response.

console.log(1, "1st.");
setTimeout(function(){
	console.log(2, "2nd");
}, 1000);
console.log(3, "3rd");
// -> 1 1st...
// -> 3 3rd
// -> 2 2nd

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 = []; 
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){
				// and so on until done...
			}
		});
	}
});
getUser(1); // get a list of connections
Synchronous code (with multiple embedded callbacks) is also slower

Promises

alt text

A JS promise lets you make asynchronous requests and use the result when a response is received.

Promises

  • Javascript's fetch() 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 fetch() response is handled using 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);
	});

Async/Await

  • Use async/await to wait for a promise to be fulfilled.
  • Remove await in the example to change the order
(async function(){ 
  // 1st
  console.log("⭐️ first");
  
  // 2nd - 👉 remove the await keyword to change the order
  await fetch("https://jsonplaceholder.typicode.com/todos")
    .then((response) => response.json())
    .then((json) => console.log(json[0]));
  
  // 3rd
  console.log("🟢 last");
})()

Fetch in a function

async function fetchFunction(){
    let jsonData;
    await fetch('https://jsonplaceholder.typicode.com/todos')
        .then(response => response.json())
        .then(json => { jsonData = json; });
    return jsonData;    
}

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 ...

<details class="slides-small"> <summary>What is the order?</summary> Left: 1,2; Right: 2,1<br> </details>

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(); ```