[46장] 제너레이터와 async/await (2)

2022. 2. 15. 21:00책/자바스크립트 딥다이브

5. 제너레이터 활용

1) 이터러블 구현

제너레이터 함수를 쓰면 이터레이션 프로토콜을 준수해 이터러블을 만드는 방식보다 간단히 이터러블 구현 가능함.

간단해지는 이유는 제너레이터 객체가 이터러블이면서 이터레이터라 중간에 [Symbol.iterator]랑 next 메서드를 만들어줄 필요가 없어서임

 

2) 비동기 처리

프로미스의 후속 처리 메서드(then/catch/finally)없이도 비동기 처리 결과를 반환하도록 구현이 가능하다.

근데 사실 제너레이터로 만들면 코드 가독성이 구려서 실제로 쓰진 않음 ㅅㄱ

const async = generatorFunc => {
    const generator = generatorFunc();

    const onResolved = arg => {
        const result = generator.next(arg);

        return result.done
            ? result.value
            : result.value.then(res => onResolved(res));
    };

    return onResolved;
}

async(function* fetchTodo(){
    const url = 'https://jsonplaceholder.typicode.com/todos/1';
    const response = yield fetch(url);
    const todo = yield response.json();
    console.log(todo);
})();

제너레이터 실행기의 이해를 돕기 위한 예제이지만 완벽하진 않다 (심지어 코드도 개어려움)

혹여나 제너레이터 실행기가 필요하다면 직접 구현하지 말고 라이브러리 찾아 써라(co 라이브러리 같은 거 있음)

코드 설명은 913p 확인 ㄱㄱ

 

6. async/await (ES8)

비동기 처리를 동기 처리처럼 동작하도록 구현해주는 함수.

프로미스를 기반으로 동작하며 제너레이터보다 간단하고 가독성이 좋다.

☞ 프로미스의 후속 처리 메서드 없이 프로미스가 처리 결과를 반환하도록 구현할 수 있다

 

1) async

async 함수는 async 키워드를 사용해 정의하며 (음?) 언제나 프로미스를 반환한다.

이때, async 함수의 반환 값이 프로미스가 아니더라도 암묵적으로 반환 값을 resolve 하는 프로미스를 반환한다.

// async 함수 선언문
async function 함수(n) { return n; }
함수(1).then(v => console.log(v)); // 1

// async 함수 표현식
const 함수2 = async function(n) { return n; };
함수2(2).then(v => console.log(v)); // 2

// async 화살표 함수
const 함수3 = async n => n;
함수3(3).then(v => console.log(v)); // 3

// async 메서드
const obj = {
    async 함수4(n) { return n; }
};
obj.함수4(4).then(v => console.log(v)); // 4

// async 클래스 메서드
class MyClass {
    async 함수5(n) { return n; }
}
const myClass = new MyClass();
myClass.함수5(5).then(v => console.log(v)); // 5

* 클래스의 constructor 메서드는 인스턴스를 반환해야 하므로 async 메서드가 될 수 없다 (async = 프로미스 반환)

 

2) await 키워드

프로미스가 settled 상태가 되기까지 대기하다가 settled 되면 프로미스가 resolve한 처리 결과를 반환한다.

반드시 async 함수 내부에서 사용해야 한다.

const getUser = async id => {
    const res = await fetch('http://어딘가');
    const { name } = await res.json();
    console.log(name);
};

getUser('존잘남');

3) 에러처리

비동기 처리를 위한 콜백 패턴은 에러 처리가 어렵다는 것이었다.

비동기 함수의 콜백 함수를 호출하는게 비동기 함수가 아니다보니 전파되는 에러를 잡아줄 대상이 없어 try ... catch 문을 사용할 수 없었다.

 

하지만 async/await 는 try ... catch 문을 사용할 수 있다.

프로미스를 반환하는 비동기 함수는 명시적으로 호출할 수 있기 때문이다. 즉, 호출자가 명확하다.

 

이때 async 함수 내부에서 try ... catch 문으로 에러 처리를 하지 않더라도 async 함수 자체가 에러가 발생하면 reject하는 프로미스를 반환하기 때문에 Promise.prototype.catch 후속 처리 메서드를 사용해도 에러 캐치가 가능하다.

// async 내부에서 try ... catch를 써도 되고
const getUser = async id => {
    try {
        const res = await fetch('http://어딘가');
        const { name } = await res.json();
        console.log(name);
    } catch (err) {
        console.error(err);
    }
};

// 이런 방식도 가능
const getUser = async id => {
    const res = await fetch('http://어딘가');
    const { name } = await res.json();
    return name;
};
getUser()
    .then(console.log)
    .catch(console.error);

getUser('존잘남');

' > 자바스크립트 딥다이브' 카테고리의 다른 글

[48장] 모듈  (0) 2022.02.16
[47장] 에러 처리  (0) 2022.02.16
[46장] 제너레이터와 async/await  (0) 2022.02.15
[45장] 프로미스(3)  (0) 2022.02.15
[45장] 프로미스(2)  (0) 2022.02.15