1. 직렬적으로 태스크를 수행하는 방식이다.
2. 요청을 보낸 후 응답을 받아야 다음 동작 이루어짐
3. 어떤 태스크를 처리할 동안 나머지 태스크는 대기한다.
4. 실제로 cpu가 느려지는 것은 아니지만 시스템의 전체적인 효율 저하
1. 병렬적으로 태스크를 수행
2. 요청 보낸 후 응답여부와 상관없이 다음 태스크가 동작, 효율적 자원 사용가능
3. 비동기요청시 응답 후 처리할 '콜백함수'를 함께 알려주고, 따라서 해당 태스크가 완료되었을 때 '콜백함수'가 호출된다.
* 자바스크립트는 비동기처리를 위한 하나의 패턴으로 콜백함수를 사용한다. 하지만 전통적 콜백패턴 : 콜백헬, 가독성 나쁨, 비동기처리 중 발생한 에러처리 및 여러개의 비동기처리를 한번에 처리하기 어려움
* 그래서 `Promise` 라는 비동기처리를 위한 또 다른 패턴을 도입
* `Promise` : 전통적 콜백패턴이 가진 단점 보완, 비동기처리 시점을 명확하게 표현할 수 있다는 장점이 있다.
* `Propmise`는 `Promise 생성자함수`를 통해 인스턴스화한다, Promise생성자함수는 비동기 작업을 수행할 콜백함수를 인자로 전달받는데 이 콜백함수는 resolve와 reject함수를 인자로 전달받는다.
//Promise 객체의 생성
const promise = new Promise((resolve, reject) => {
//비동기작업을 수행한다.
if () {
resolve('result')
}
else {
reject('failure reason')
}
})
//promise는 비동기처리가 성공/실패했는지 등의 상태(state)정보를 가진다.
* pending : 비동기처리가 아직 수행되지 않은 상태
* fulfilled : (성공) 비동기처리 수행된 상태
* rejected : (실패) 비동기처리 수행된 상태
* settled : (성공 또는 실패) 비동기처리 수행된 상태
::: 비동기함수 내에서 Promise객체를 생성하고 내부에서 비동기처리를 구현한다.
::: 이 때, 비동기처리에 성공하면 resolve 메소드
를 호출,
::: 이 때, resolve메소드의 인자로 비동기처리결과를 전달하는데, 이 처리결과는 Promise객체의 후속처리 메소드
로 전달된다.
::: 만약, 비동기처리에 실패하면 : reject 메소드
를 호출,
::: 이 때, reject메소드의 인자로 에러 메시지를 전달한다. 이 에러 메시지는 Promise 객체의 후속처리 메소드로 전달된다.
then
- then 메소드는
두개의 콜백함수
를 인자로 전달받는다.
첫번째 콜백함수 = 성공(fullfilled, resolve함수가 호출된 상태) 시 호출된다.
두번째 콜백함수 = 실패(rejected, reject함수가 호출된 상태) 시 호출된다.
then 메소드는 Promise를 반환
한다.
catch
- 예외가 발생하면(비동기처리에서 발생한 에러와 then메소드에서 발생한 에러) 호출된다.
catch메소드는 Promise를 반환
한다.
::: 비동기함수의 처리결과를 가지고 다른 비동기함수를 호출 해야하는 경우, 함수의 호출이 중첩되어 복잡도가 높아진다 === 콜백헬 발생
::: Promise는 후속처리메소드인 then
이나 catch
로 메소드를 체이닝(chainning)
하여 여러개의 프로미스를 연결하여 사용해서 콜백헬을 해결한다.
::: 따라서, then메소드가 Promise객체를 반환하도록 하면 여러개의 프로미스를 연결하여 사용가능 (then 메소드는 기본적으로 Promise를 반환)
//async와 await 기본문법
async function 함수명() {
await 비동기처리메소드명();
}
//아래 예시함수를 호출하면 result가 '1'인 이행프라미스가 반환된다.
async function f() {
return 1;
}
f().then(alert);
//위 함수에서 1을 Promise.resolve로 감싸도 같은결과 반환
async function f() {
return Promise.resolve(1);
}
f().then(alert);
* 즉, async가 붙은 함수는 반드시 프라미스를 반환하고 프라미스가 아닌 것은 프라미스로 감싸서 반환한다.
기다리는
역할을 하고, 결과는 그 이후에 반환된다.
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('완료'), 1000)
});
//프라미스가 이행 될 때까지 기다림
let result = await promise;
alert(result);
}
f();
let result = await promise;
라인에서 실행이 잠시 '중단'되었다가 프라미스가 처리되면 실행이 재개된다.result
값이 변수 result에 할당된다.
await
=== promise가 처리 될 때까지 함수실행을 기다리게 만든다.- 프라미스가 처리되면 그 결과와 함께 실행이 재개되며, 프라미스가 처리되길 기다리는 동안엔
- 엔진이 다른 일(다른 스크립트를 실행, 이벤트 처리 등등)을 할 수 있기 때문에 cpu리소스가 낭비되지 않는다.
await
를 사용하지 않았다면 데이터를 받아 온 시점에 콘솔을 출력할 수 있게 콜백함수나 .then()
등을 사용해야 한다.await
는 promise.then
보다 좀더 세련되게 프라미스의 result
값을 얻을 수 있다. promise.then
보다 가독성 좋고 쓰기 쉬움async function f() {
try {
let response = await fetch('http://유효_하지_않은_주소');
} catch(err) {
//type Error: failed to fetch
alert(err);
}
}
f();
async/await
을 사용하면await
가 대기를 처리해주기 때문에.then
이 거의 필요하지 않다..catch
대신 일반try..catch
를 사용할 수 있다.- 하지만, 문법제약 때문에
async
함수 바깥의 최상위레벨 코드에서는await
를 사용할 수 없다.- 그렇기 때문에 관행처럼
.then/catch
를 추가해 최종결과나 처리되지 못한 에러를 다룬다.