Synchronous | Asynchronous API

Jay·2022년 9월 3일
0
post-thumbnail

CallBack Functions

Before discussing synchronous and asynchronous APIs, let us talk about callback functions. Simply put, callback functions are functions that are taken as arguments, thus act as a component of another function. I like to think them as small cogs that belong to a bigger cog. Another way is to think of them as a type of helper functions. Thus they are run inside another function. Throughout this post, I will mainly refer to callback functions as simply functions run inside an API.

Synchronous vs. Asynchronous APIs

The main difference between these two concepts lies in order and timing. Let us think of three functions A, B, and C. If these functions are processed "in order", meaning A then B then C, (going line by line) this is considered synchronous. If they are processed all at the same time (as in C runs as A and B are running), the process in then asynchronous.

Let us imagine a situation where you're waiting for a webpage to run. If the process is synchronous, then it would take quite a long time, as you would have to retrieve all the external data in order step by step, without being able to process the requests all at the same time. So in this case, you would want to use asynchronous API to shorten time taken to fetch the page.

This time, let us imagine a situation when you're creating a new post then reading the post. Here, asynchronized process can cause error, as it takes some time to actually create and save the newly created post. If we request the page before it is actually made, then there is a problem. We can see that the main cause of the problem is dependency. So in this case, you would want to use a synchronoyus API to prevent such errors.

I. XMLHttpRequest

function myCallback() {
	const req = new XMLHttpRequest();
    req.open("get", "http://numbersapi.com/random?min=1&max=200");
    req.send();
    req.addEventListener("load", (res)=>{
    	console.log(res);
        const num = res.target.response.split(" ")[0];
        const reqBoard = new XMLHttpRequest();
        reqBoard.open("get", `http://koreanjson.com/posts/${num}`);
       	reqBoard.send();
        reqBoard.addEventListener("load", (res)=> {
        	console.log(res);
        	const writer = JSON.parse(res.target.response).UserId;
       		const reqMore = new XMLHttpRequest();
       		reqMore.open("get", `http://koreanjson.com/userId=${writer}`);
       		reqMore.send();
        	reqMore.addEventListener("load", ()=>"all complete")
       	})
    }) 
}

The API named myCallback() above is an example of a callback using XMLHttpRequest (which is not frequently in use nowadays, but used to illustrate early versions of callbacks). A random number is chosen, and when the result is loaded, it is passed as an argument into the next request. Here, notice the result of one function is used as an input to the next function, thus a dependency exists. Hence the need for synchronous functions. We see that every time a callback is called, indentation makes harder to read and interpret code, as well as extending API. This is frequently referred to as callback hell.

II. Promise

To solve the problem of callback hells, the concept of Promise came into use.

function myPromise() {
	//1
	axios.get("http://numbersapi.com/random?min=1&max=200").then((res)=>{
	//3
    	const num = res.data.split(" ")[0];
    	return axios.get(`http://koreanjson.com/posts/${num}`)
	})
    .then((res)=>{
    //4
    	const writer = res.data.UserId;
    	return axios.get(`http://koreanjson.com/posts?userId=${writer}`)
            })
    .then((res)=>{
    //5
    console.log("all complete..but that was quite unpredictable..")
    })
 	//2
}

Promise uses return statement to pass in the result as the argument of the next function. This is referred to as promise chaining. As we see above, this removes the need to indent every time callback function is called. However, one critical problem is that it is difficult for the reader to follow the sequence of which lines are run (we see that first the axios get request is sent, then portion labeled 2 - bits of code after the promise chains - is run). This makes the lines of code hard to follow.

III. Async Await

Finally, to resolve amentioned problems, asyn-await comes into practice.

async function myAsyncAwait() {
	const res1 = await axios.get();
	const num = res1.data.split(" ")[0];

    const res2 = await axios.get();
    const writer = res2.data.UserId;

    const res3 = await axios.get();
    console.log(res3.data);
}

The code above goes through the same callback functions: it gets a random number, then finds the corresponding data, then shows the data onto the page. It is easy to see at first glance how simple and clean the code becomes. The keyword await marks that the line of code takes some time to process. Thus, it only runs the next line after the appropriate result is returned. In order to use the await keyword, the API needs to be marked async.

0개의 댓글