동기식 (Synchronous) / 비동기식 (Asynchronous)
- 동기식
먼저 시작된 하나의 작업이 끝날 때까지 다른 작업을 시작하지 않고 기다렸다가 다 끝나면 새로운 작업을 시작하는 방식
- 비동기식
동기식 방식과는 다르게 먼저 시작된 작업의 완료 여부와는 상관없이 새로운 작업을 시작하는 방식
작업의 순서가 확실하지 않아서 나중에 시작된 작업이 먼저 끝나는 경우도 발생
< 자바스크립트 비동기 처리 >
자바스크립트는 기본적으로 비동기적으로 동작을 한다.
개발하다 보면 비동기식으로 동작하는 부분이 동기적으로 동작해야 하는 경우가 생긴다.
이럴 때 비동기식 동작이 동기식으로 동작하도록 해주는 걸 비동기 처리라고 한다.
1. 콜백함수 사용
2. promise
3. promise 를 활용한 asyne/await
콜백함수를 남용하게 되면 가독성과 에러 처리 등에서 불편함이 발생한다.
이를 해소하기 위해 ES6 에서 비동기 처리의 새로운 방법으로 promise 객체 가 등장한다.
promise 객체는 비동기 작업의 최종완료(또는 실패)와 그 결과 값을 나타낸다.
new Promise() 객체를 생성하여 콜백 함수를 선언할 수 있는데 이때의 인자는 resolve, reject 를 사용한다.
resolve 는 결과가 성공인 promise 객체를 반환하고 reject 는 결과가 실패인 promise 객체를 반환한다.
반환된 promise 객체를 처리할 때..... 성공 시 then 을 사용하고 실패시 catch 를 사용하여 처리
성공시, resolve, then
실패시, reject, catch
정리 :
promise 객체!!!!!를 생성하고 인자는 resolve , reject 사용
resolve 는 결과가 성공인 promise 객체!!!!!를 반환한다.
반환된 객체 처리는 then 처리
let myFirstPromise = new Promise((resolve, reject) => {
setTimeout(function(){
// 성공 시 resolve 사용
resolve('Success!');
}, 3000);
});
// 성공 시 then 사용하여 결과 처리
myFirstPromise.then((successMessage) => {
console.log('Yay!' + successMessage);
});
// 결과
// (3초 대기)
// Yay! Success!
// 종료
let myFirstPromise = new Promise((resolve, reject) => {
setTimeout(function(){
// 실패 시 reject 사용
reject(new Error('Fail'));
}, 3000);
});
// reject 를 사용하여 promise 객체를 반환하기 때문에 then 은 실행되지 않음
myFirstPromise.then((successMessage) => {
console.log('Yay!' + successMessage);
})
// 실패 시 catch 사용하여 결과 처리
.catch((reson) => {
console.log('여기서 거부된 프로미스(' + reason + ')를 처리하세요');
});
// 결과
// (3초 대기)
// 여기서 거부된 프로미스(Error: Fail) 를 처리하세요
// 종료
그렇다면 Promise 방식이 콜백 함수보다 좋은 점이 무엇일까?
function a() {
return new Promise({
// ...
});
}
function b() {
return new Promise({
// ...
});
}
function c() {
return new Promise({
// ...
});
}
myFirstPromise()
.then(a)
.then(b)
.then(c);
콜백 함수를 사용했으면 훨씬 길어지고 복잡해졌을 코드도 위 예시와 같이 Promise 객체를 반환하면 여러 개의 then을 연결하여 간단히 처리할 수 있다.
Promise를 활용한 async/await
ES2017에 새로 추가된 async/await 는 위에서 알아봤던 Promise 객체를 기반으로 사용한다.
기존 Promise와의 차이점
가장 큰 차이점은 위에서 배웠던 resolve, reject, then, catch를 쓰지 않는다는 것이다.
아니! 위 내용 익히고 오라더니 열심히 공부하고 오니까 안 쓴다고요?????????
사실 async/await만 사용하려면 저 4가지는 어떻게 사용했는지 잊어버려도 된다.
async
- async 사용 예시
// async 키워드만 붙이면 된다.
async function hello() {
return 'Hello';
}
function callHello() {
const r = hello();
console.log(r);
}
callHello();
- 결과
# 시작
Promise { 'Hello' }
# 끝
놀랍게도 위에서 사용했던 new Promise()고 뭐고 아무것도 없다.
그냥 기본 메소드 앞에 async만 붙이면 반환되는 값이 Promise 객체가 된다.
Promise 객체가 무엇인지는 이미 익히고 온 여러분은 이 간단한 예시만으로 async를 어떻게 쓰는지 이해가 다 됐을 거라 생각된다.
그런데 우리는 위 예시처럼 객체 형태의 Promise { 'Hello' }가 아니라 그 안에 있는 String 형태의 Hello를 출력하고 싶다.
어떻게 해야 할까??
다음 설명을 보도록 하자.
await
이제 우리는 async를 어떻게 쓰는지 또 어떤 결과가 나오는지는 알고 있다.
이번엔 그 결과를 어떻게 내가 원하는 방식으로 사용할지를 알아보도록 하겠다.
- await 사용 예시
async function hello() {
return 'Hello';
}
// (2) 새로 추가된 async 키워드
async function callHello() {
// (1) 새로 추가된 await 키워드
const r = await hello();
console.log(r);
}
callHello();
- 결과
# 시작
Hello
# 끝
자 달라진 내용을 살펴보자.
먼저 (1) 부분을 보면 hello(); 앞에 await 키워드가 추가됐다.
await가 붙으면 반환된 Promise 객체에서 실제 hello() 메소드의 반환 값인 String 값을 뽑아낸다고 보면 된다.
그렇다면 위 예시의 r 값에 String 형태의 Hello가 입력될 것이다.
출력 결과를 보면 await가 붙기 전이랑 다르게 r을 출력하면 문자열만 출력되는 걸 확인 할 수 있다.
다음은 (2) 부분을 보면 callHello() 메소드에도 async가 추가됐다.
await 키워드는 async 키워드가 붙은 메소드에서만 사용할 수 있다.
만약 async가 없는 메소드에서 await를 사용한다면 아래와 같은 SyntaxError가 발생한다.
결과 처리방법
위 내용은 굉장히 쉬워서 이해하는 데에 어려움이 없었을 것 같다.
하지만 아직 끝난 게 아니다.
이제 우리는 성공과 실패에 대해 처리를 해서 마무리를 지어줘야 하는데 기존 Promise 방식으로 생각하면 then, catch 부분을 처리해줘야 한다.
당연히 이 부분도 훨씬 쉽다.
위에서 사용한 예시를 활용하여 바로 알아보자!
- 성공 처리 예시
async function hello() {
return 'Hello';
}
async function callHello() {
// 새로 추가된 try 키워드
try {
const r = await hello();
console.log('성공: ' + r);
} catch (e) {
console.log('실패: ' + e.message);
}
}
callHello();
- 결과
# 시작
성공: Hello
# 끝
- 실패 처리 예시
async function hello() {
throw new Error(`Fail!`);
}
async function callHello() {
try {
const r = await hello();
console.log(r);
// 새로 추가된 catch 키워드
} catch (e) {
console.log(e.message);
}
}
callHello();
- 결과
# 시작
실패: Fail!
# 끝
기존 then과 catch는 각각 try-catch로 바뀌었다.
위 예시와 같이 await를 붙인 메소드의 결과가 성공일 경우는 try 부분이 실행되고 실패일 경우는 catch 부분이 실행된다.
이 내용은 기존 C언어나 Java언어 등에서 사용하는 try-catch 개념과 비슷하기 때문에 별다른 설명 없이도 충분히 이해가 될 거라 생각한다.
여기까지 자바스크립트의 3가지 비동기 처리 방법에 대해서 알아봤다.
참고 블로그
공식 문서 개인정리...
먼저 비동기 함수를 async 함수로 만들기 위하여 function() 앞에 async 키워드를 추가한다.
async function() 은 await 키워드가 비동기 코드를 호출할 수 있게 해주는 함수이다.
function hello() { return "Hello" };
hello();
↑
위의 함수는 "Hello" 를 반환한다.
그러나 이 함수 앞에 async 키워드를 추가하면
이제 코드가 Promise 를 반환한다....!!
이것이 async 특징 중 하나이다.
이렇게 작성할 수도 있다.
let hello = async fuction() { return "Hello" }
hello();
화살표 함수를 사용하면 아래처럼 쓸 수 있다.
let hello = async () => { return "Hello" }
그리고 실제로는 fulfil Promise 가 반환되기 때문에 반환된 값을 사용하기 위해선
.then() 블럭을 사용해야 한다.
hello().then((value) => console.log(value))
짧게 표현하면 아래와 같이 쓸 수 있다.
hello().then(console.log)
정리하면 async 를 함수와 깉이 사용하면 결과를 직접 반환하는게 아니라 Promise 를 반환하게 된다.
또한 동기식 함수는 await 사용을 위한 지원과 함께 실행되는 잠재적인 오버헤드를 피할 수 있다.
'🤹🏻♀️ Javascript' 카테고리의 다른 글
moment 참고자료 (0) | 2022.03.06 |
---|---|
Ajax, Axios, Fetch (0) | 2022.01.31 |
객체 순회하기 (0) | 2021.11.06 |
클래스, const 객체, 메서드, map 메서드 (0) | 2021.11.06 |
제로초 자바스크립트 7장 (가위바위보) (0) | 2021.10.24 |