현재 실행중인 코드가 완료되어야 다음 코드가 실행되는 것
자바스크립트는 단일 스레드(싱글 스레드)를 가지고 있기 때문에 동기식 언어
💡 스레드란? 프로그램이 작업을 완료하는 데 사용하는 단일 프로세스로, 하나의 스레드는 한 가지의 작업만 수행 가능하다
console.log('hi');
console.log('hello');
console.log('bye');
// hi
// hello
// bye
하나의 동작이 완료되지 않아도 다음 코드가 실행되는 것
네트워크 통신이나 파일을 읽어오는 등 시간이 오래 걸리는 작업은 비동기적으로 처리하는 것이 좋다. 서버의 응답을 기다리는 동안 아무것도 실행되지 않으면 프로그램 실행 시간이 길어지고 화면이 멈춘 것처럼 보일 수 있기 때문이다.
❓ 그렇다면 싱글 스레드를 가지고 있는 자바스크립트가 비동기적으로 작업할 수 있는 이유는?
Web API가 멀티 스레드로 동작하기 때문!
console.log(1);
setTimeout(() => console.log(2), 1000);
console.log(3);
// 1
// 3
// 2 -> 1초 후 실행.
// setTimeout: 지연 시간 뒤에 첫 번째 파라미터로 전달받은 콜백함수를 실행시키는 대표적 비동기 함수
콜백함수 대신에 비동기를 간편하게 처리할 수 있는 내장 Object로, ES6에서 도입되었다. 주로 서버에서 받아온 데이터를 화면에 나타낼 때 사용된다.
const promise = new Promise((resolve, reject) => {
// executor (실행함수)
})
새로운 Promise 객체가 생성되면 바로 executor 함수가 자동으로 실행된다는 점을 유의하자! 이 부분에서 원하는 일이 처리되고, 성공 여부에 따라서 자바스크립트가 자체 제공하는 resolve
나 reject
함수가 호출된다.
resolve
: 일이 정상적으로 수행되었을 때 최종 데이터(value)를 전달해주는 콜백함수reject
: 문제가 생기면 에러 객체를 나타내는 error와 함께 호출되는 콜백함수둘중 한가지는 반드시 호출해야 한다.
이미 처리가 완료된 프로미스 이후에 resolve, reject를 호출하면 무시된다.
// 1. promise 제작 단계
// 성공
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success') // 성공적으로 실행되면 2초 뒤 'success'라는 값 전달
}, 2000);
});
// 실패
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject (new Error('no network')); // 실패하면 2초 뒤 Error 객체로 값 전달
}, 2000);
});
// 2. promise 소비 단계 (then/catch로 값 처리)
promise
.then(value => {
console.log(value);
// then 메서드는 성공 케이스만 다룬다 → resolve되면 'success'라는 값 출력
})
.catch(error => {
console.log(error);
// catch 메서드는 에러 케이스만 다룬다 → reject되면 'no network' 값 출력
})
.finally(() => {console.log('finally')}) // 성공 여부에 상관없이 무조건 출력
밑의 예시는 사용자 로그인 인증 단계에서 사용될 수 있는 프로미스 체이닝을 보여주고 있다. (사용자 정보 파싱 → 인증 → 정보 표시)
var userInfo = {
id: 'abc@naver.com',
pw: '*****'
};
function parseValue() {
return new Promise({
// ...
});
}
function auth() {
return new Promise({
// ...
});
}
function display() {
return new Promise({
// ...
});
}
getData(userInfo)
.then(parseValue)
.then(auth)
.then(display);
콜백 함수와 Promise보다 비동기 처리를 더 깔끔하게 사용할 수 있게 해주는 문법으로,
ES2017에서 도입되었다.
Promise의 syntactic sugar이다.
💡 syntactic sugar : 문법적인 기능은 유지하되, 읽고 쓸 때 더욱 간편해지는 프로그래밍 문법
함수 앞에 async
가 붙으면 반드시 프라미스를 반환하고, 프라미스가 아닌 것은 프라미스로 감싸 반환한다. await
은 프라미스가 처리될 때까지 함수 실행을 기다렸다가 작동되며, async
함수 내에서만 작동한다는 점을 유의하자!
async function func() {
await // 비동기적으로 실행되는 코드
}
❗ 사용 예시
function fetchItems() {
return new Promise(function(resolve, reject) {
var items = [1,2,3];
resolve(items)
});
}
async function logItems() {
var resultItems = await fetchItems();
// 프라미스가 처리되면 프라미스 객체의 items 배열 결과값을 변수에 저장
console.log(resultItems); // [1,2,3]
}
async/await
에서는 try/catch로 예외 처리를 한다.
try {이걸 해보고 안되면} catch {이걸 해주세요}
try문이 잘 실행되면 catch문을 넘어간다.
❗ 사용 예시
async function f() {
try {
let response = await fetch('http://유효하지-않은-주소');
let user = await response.json();
} catch(err) {
// fetch와 response.json에서 발행한 에러 모두를 여기서 잡는다.
alert(err);
}
}
f();
참고 자료