비동기 처리의 이해
자바스크립트는 동기적(Synchronous)으로 동작하는 언어이다. 따라서 순차적으로 코드가 실행된다.
동기라는 단어는 동일한 기차길이라고 생각하면 이해하기 쉽다. (from 얄팍한 코딩사전)
우리가 집안일을 할 때, 세탁기를 돌려 놓고 다른 집안일을 하는 것(비동기)이 더 빠르게 일을 처리할 수 있는 것처럼 프로그램이 실행될 때도 비동기(Asynchronous) 처리를 해야 하는 상황이 존재할 수 있다.
예를 들어, 다음과 같은 코드는 work()함수가 종료되고 나서야 console.log('다음 작업')이 실행된다.
따라서, 만약 work() 함수가 굉장히 오래걸리는 함수라면 그동안 다른 코드들이 실행되지 못하므로 사용자가 불편을 느끼는 상황이 발생할 수 있다.
이런 경우에 work() 함수 안에서 비동기 처리를 해준다면 work() 함수가 실행되는 동안에 다른 작업도 실행할 수 있다.
아래 코드와 같이 setTimeout을 사용하면 비동기 처리를 할 수 있다.
setTimeout에서 2번째 파라미터로 0을 넣어줬지만 실제로는 4ms 후에 코드를 실행시킨다고 한다.
아래와 같이 작업이 종료된 후 실행되는 함수인 callback함수를 사용하여 작성할 수도 있다.
하지만 callback 함수를 여러 번 사용해야 하는 경우 아래와 같이 callback 지옥에 빠질 수 있다.
Promise를 사용하면 콜백 지옥을 피할 수 있다.
function increaseAndPrint(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const increased = n + 1;
console.log(increased);
if (increased === 5) {
const error = new Error();
error.name = 'ValueIsFiveError';
reject(error);
console.log('작업 끝!');
}
resolve(increased);
}, 1000);
});
}
increaseAndPrint(0)
.then((n) => increaseAndPrint(n))
.then((n) => increaseAndPrint(n))
.then((n) => increaseAndPrint(n))
.then((n) => increaseAndPrint(n))
.catch((e) => console.log(e));
아래와 같이 조금더 간결하게 작성할 수도 있다.
function increaseAndPrint(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const increased = n + 1;
console.log(increased);
if (increased === 5) {
const error = new Error();
error.name = 'ValueIsFiveError';
reject(error);
console.log('작업 끝!');
}
resolve(increased);
}, 1000);
});
}
increaseAndPrint(0)
.then(increaseAndPrint)
.then(increaseAndPrint)
.then(increaseAndPrint)
.then(increaseAndPrint)
.catch((e) => console.log(e));
아래와 같이 async, await을 사용하면 Promise를 더 쉽게 사용할 수 있다.
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function process() {
console.log('작업 1');
await sleep(1000);
console.log('작업 2');
}
process();
console.log('다른 작업');
// 작업1
// 다른 작업
// 작업2
async 함수는 promise를 반환하기 때문에 아래와 같이 작성할 수도 있다.
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function process() {
console.log('작업 1');
await sleep(1000);
console.log('작업 2');
return '작업 끝';
}
process().then((v) => console.log(v));
throw error와 try catch를 사용하면 에러를 던지고 잡아낼 수 있다.
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function makeError() {
await sleep(1000);
const error = new Error();
throw error;
}
async function process() {
try {
await makeError();
} catch (e) {
console.log(e);
}
}
process();
아래와 같은 코드가 있을 때, 만약 여러개의 Promise를 동시에 처리하고 싶다면 Promise.all 또는 Promise.race를 사용하면 된다.
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
const getDog = async () => {
await sleep(1000);
return 'Dog';
};
const getRabbit = async () => {
await sleep(500);
return 'Rabbit';
};
const getTurtle = async () => {
await sleep(2000);
return 'Turtle';
};
async function process() {
console.log(await getDog());
console.log(await getRabbit());
console.log(await getTurtle());
}
process();
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
const getDog = async () => {
await sleep(1000);
return 'Dog';
};
const getRabbit = async () => {
await sleep(500);
return 'Rabbit';
};
const getTurtle = async () => {
await sleep(2000);
return 'Turtle';
};
async function process() {
const results = await Promise.all([getDog(), getRabbit(), getTurtle()]);
console.log(results); // 3초 후 ["Dog", "Rabbit", "Turtle"]
}
process();
Promise.race는 가장 빠르게 반환하는 것을 알려준다.
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
const getDog = async () => {
await sleep(1000);
return 'Dog';
};
const getRabbit = async () => {
await sleep(500);
return 'Rabbit';
};
const getTurtle = async () => {
await sleep(2000);
return 'Turtle';
};
async function process() {
const results = await Promise.race([getDog(), getRabbit(), getTurtle()]);
console.log(results); // Rabit
}
process();
all은 하나라도 에러가 발생하면 에러를 잡아낼 수 있지만,
race는 가장 빨리 끝나는 것만 에러를 잡아낼 수 있다. 그 이후에 끝나는 것들은 에러를 잡아내지 못함.
'WEB🔨 > 자바스크립트' 카테고리의 다른 글
[JavaScript] JS Flow - 함수 선언문과 함수 표현식 (0) | 2020.06.12 |
---|---|
[JavaScript] JS Flow - 호이스팅(hoisting) (0) | 2020.06.12 |
[JavaScript] 부드럽게 올라가는 Top버튼 만드는 방법 (0) | 2020.04.22 |
[JavaScript] What is localStorage? (0) | 2020.03.05 |
[JavaScript] What is JSON? (0) | 2020.03.05 |