동기
한 작업이 완전히 끝나야 다음 작업으로 넘어감
ex)
console.log(1);
console.log(2);
console.log(3);
/**
1
2
3
1, 2, 3 순서대로 출력된다.
*/
비동기
한 작업이 끝나지 않고 다음 작업으로 넘어간다.
ex)
console.log(1);
setTimeout(function afterTwoSeconds() {
console.log(2);
}, 2000);
console.log(3);
/**
1
3
2
1, 2, (2초 뒤), 3으로 찍힐 것 같지만 1,3,2로 출력된다.
setTimeout은 비동기 함수이기 때문에!
*/
좀 더 쉽게 이해해보자!
ex) 커피숍
▪️ 동기 : 손님 한 명이 주문 후 커피를 받아가는 것 까지 마쳐야 다음 손님의 주문을 받을 수 있다.
▪️ 비동기 : 주문은 순서대로 받는다. 앞 사람이 커피를 받아갔는지는 알 바가 아니다. 커피는 나오는대로 받아가면 된다!
▪️ 자바스크립트 자체는 동기이다.
비동기 사례
ajax
function getData() {
var tableData;
$.get('https://domain.com/products/1', function(response) {
tableData = response;
});
return tableData;
}
console.log(getData()); // undefined
위의 코드에서 undefined가 찍힌 이유는 ajax 통신은 비동기 방식으로 동작하기 때문이다.
get을 한 뒤 요청 받은 값을 받을 때 까지 기다리지 않고 tableData를 return 시켰기 때문에 undefiend가 찍힌 것.
setTimeout()
위에서 비동기를 설명한 코드와 같다.
콜백 함수
function getData(cb) {
$.get('https://domain.com/products/1', function(res) {
cb(res);
});
}
getData(function(tableData) {
console.log(tableData);
});
콜백 함수를 사용하면 특정 로직이 끝났을 때 원하는 동작을 실행 시킬 수 있다.
하지만 콜백 함수로 비동기 처리를 해결하게 되면 엄청난 콜백 지옥에 빠지게 될 수 있다..!
콜백 지옥 탈출 방법 두 가지
Promise
・ 프로미스는 자바스크립트 비동기 처리에 사용되는 객체!
위의 예제를 promise를 사용한 예제로 변환해보겠다.
function getData(cb) {
return new Promise(function(resolve, reject) {
$.get('url/products/1', function(res) {
resolve(res);
});
});
}
//getData()의 실행이 끝나면 then을 호출된다.
getData().then(function(tableData) { // then에 resolve();된 값이 전달된다.
console.log(tableData);
});
이렇게 바꿀 수 있다!!
Promise 의 사용법에 대해 더 알아보자.
// promise 객체 생성 시, 콜백 함수를 선언 할 수 있다.
// 콜백 함수의 첫번째 인자로는 resolve();
// 두번째 인자로는 reject();가 들어온다.
new Promise(function(resolve, reject) {
resolve(); // resolve();를 하면 이행 상태가 된다.
resolve('값'); // resolve안에 값을 넣어 전달하면 - (1)
reject(); // reject();를 하게 되면 실패 상태가 된다.
reject(new Error('error')); // 실패 한 이유를 reject()에 넣어 전달하면 - (2)
});
getData().then(function(data) { // then의 첫번째 인자에서 받아 올 수 있다. - (1)
console.log(data);
}).catch(function(err) { // catch 절에서 에러를 받을 수 있다. - (2)
console.log(err);
});
프로미스 사용법을 활용한 예제
function getData() {
return new Promise(function(resolve, reject) {
$.get('url/products/1', function(res) {
if(res) {
resolve(res);
}
reject(new Error('error'));
});
});
}
getData().then(function(data) {
console.log(data);
}).catch(function(err) {
console.log(err);
});
여러개의 프로미스 연결
function getData() {
return new Promise({
// ...
});l
}
getData()
.then(function(data) {
// ...
})
.then(function() {
// ...
})
.then(function() {
// ...
});
// then 메서드를 호출하고 나면 새로운 프로미스 객체가 반환된다!
new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(1);
}, 2000);
})
.then(function (result) {
console.log(result); // 1
return result + 10;
})
.then(function (result) {
console.log(result); // 11
return result + 20;
})
.then(function (result) {
console.log(result); // 31
});
async / await
콜백과 프로미스의 단점을 보완하고, 코드를 더 읽기 좋게 만들어준다.
async function 함수명() {
await 비동기_처리_메서드명();
}
function fetchItems() {
return new Promise(function(resolve, reject){
var items = [1, 2, 3];
resolve(items);
});
}
async function logItems() {
var resultItems = await fetchItems();
console.log(resultItems); // [1, 2, 3]
}
await은 Promise를 기다리기 위해 사용한다. await은 async function 내부에서만 사용할 수 있다.
awiat문은 Promise가 fulfill(연산이 성공적으로 완료)되거나 reject 될 때 까지 async 함수의 실행을 일시 정지하고, Promise가 fulfill 함수를 일시 정지한 부분부터 실행한다. 이때 await 문의 반환값은 Promise에서 fulfill된다.
만약 Promise가 reject 되면, await문은 reject 된 값을 throw 한다.
참고 출처 : https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/ 시리즈
'Frontend > Javascript' 카테고리의 다른 글
[javascript] 웹 페이지에서 javascript가 하는 일 (0) | 2021.09.12 |
---|---|
Javascript new (0) | 2021.08.25 |
Javascript this (4) | 2021.08.13 |