데브코스

[8주차 복습 발표] 비동기 처리

미안하다 강림이 좀 늦었다 2024. 4. 18. 14:36

 

 

Promise

지금까지는 콜백 함수를 통해 비동기 상황을 해결했다. 하지만 콜백 함수들이 여러 번 중첩되면 코드가 복잡해지고 가독성이 떨어지는 콜백 지옥 현상이 발생하기 때문에 Promise를 사용한다.

 

new Promise로 프로미스 객체를 생성하고, resolve와 reject를 파라미터로 갖는 콜백 함수를 넣는다.

이 프로미스 변수에는 then과 catch 메서드가 있다. resolve가 호출되면 then이 실행되고, reject가 호출되면 catch가 실행된다. resolve와 reject에 넣어준 인수가 각각 then과 catch로 전해진다.

finally 메서드는 끝나면 무조건 실행된다.

const condition = true;
const promise = new Promise((resolve, reject) => {
    if (condition)
        resolve('성공');
    else
        reject('실패');
})

promise
    .then((msg) => {
        console.log(msg);
    })
    .catch((msg) => {
        console.log(msg);
    })
    .finally(() => {
        console.log('마지막');
    })
    
// 성공
// 마지막

 

then이나 catch에서 다시 다른 then이나 catch를 붙일 수 있다. 이것을 promise chaining이라고 하며, 이전 then의 return 값을 다음 then의 파라미터로 넘긴다.

프로미스를 return한 경우 프로미스가 수행된 후 다음 then이나 catch가 호출된다.

const condition = true;
const promise = new Promise((resolve, reject) => {
    if (condition)
        resolve('성공');
    else
        reject('실패');
})

promise
    .then((msg) => {
        console.log(msg);
        return '이것도 성공';
    })
    .then((msg) => {
        console.log(msg);
    })
    .catch((msg) => {
        console.log(msg);
    })
    
    // 성공
    // 이것도 성공

 

 

async/await

프로미스가 콜백 지옥 현상은 해결했지만 then과 catch가 계속 반복되기 때문에 여전히 코드가 복잡하다. async/await 문법은 코드를 더 깔끔하게 줄여준다.

 

async

비동기 함수임을 나타내는 키워드로, 함수 앞에 async 키워드를 넣어주면 된다.

async 함수는 무조건 Promise 객체를 반환한다. 반환 값이 Promise가 아니라면 Promise로 감싸서 return 해 준다.

그래서 아래 코드에서 f 함수의 return 7은 return Promise.resolve(7)과 동일하다.

async function f() {
    return 7; // return Promise.resolve(7)과 동일
}

f().then(
    function (result) {
        console.log("promise resolve: ", result);
    },
    function (error) {
        console.log("promise reject: ", error);
    }
)

 

await

await는 async 함수 안에서만 동작할 수 있고, 프로미스 then() 메서드를 좀 더 쉽게 사용할 수 있게 해 준다.

promise 객체가 일을 다 할 때까지 기다리라는 의미를 가진다.

아래 코드는 3초가 걸리는 각각의 프로미스를 기다렸다가 다음 명령을 실행하는 코드이다.

async function f() {
    let promise1 = new Promise(function (resolve, reject) {
        setTimeout(() => resolve("첫 번째 쿼리"), 3000)
    });

    let result1 = await promise1;
    console.log(result1); // 첫 번쨰 쿼리

    let promise2 = new Promise(function (resolve, reject) {
        setTimeout(() => resolve("두 번째 쿼리 " + result1), 3000)
    });

    let result2 = await promise2;
    console.log(result2); // 두 번째 쿼리 첫 번째 쿼리
}

f();