Web Dev/1. JS 문법 관련

Generator와 비동기처리

hYhY1234 2021. 6. 2. 10:12
728x90

redux saga를 사용하다보니 내부가 다 Generator였다. 대강 어떻게 굴러가는진 알겠지만 Generator와 Promise가 처리되는 흐름이 영 매끄럽게 이해가 되지 않아서 Modern JavaScript Deepdive 46장을 읽어보았다. 

 

 

제너레이터란

function* test(array) {    
    for(let i = 0; i < array.length; i++){
    	yield array[i]
    }
}

const getArray = test([1,2,3,4,5])

getArray.next();
getArray.next();
getArray.next();
getArray.next();
getArray.next();
getArray.next();

 

이렇게 나온다. 제너레이터 함수를 호출하면 함수를 실행하고 끝나는게 아니라, yield키워드 가 있는데서 값을 반환한다. 그리고 제어권을 호출자에게 줘버린다. 즉, 호출자가 필요할때 .next()를 통해서 다음 동작을 재개할수있게 된다. 

 

 

제너레이터로 비동기 처리하기

async/await 키워드가 나타나기전에 제너레이터로 비동기처리를 하셨던것 같다. 

제너레이터 함수 내에서 Promise가 있는 부분에서 일단 yield를해서 제어권을 함수를 호출한 애한테 준다음, 거기서 Promise가 resolve되면 next()를 하라고 코드를 짜면 된다. 

 

const async = generatorFunc => {
	const gen = generatorFunc();
    
    const onResolved = arg => {
    	const result = gen.next(arg); console.log("result", result);
        if(result.done) {
        	return result.done
        }else if(typeof result.value?.then === 'function'){
       		result.value.then(res => onResolved(res))
        }else{
            onResolved(result.value)
        }
    }
    return onResolved;
}

(async(function* fetchTodo() {
	const response = yield new Promise((resolve) => setTimeout(() => resolve("test"), 1000));
    const todo = yield response; 
    const test = yield 3; 
    })())
    

결과가 이렇다. Promise일때는 resolve되고나서 next를 호출하고, promise 아닌건 그냥 호출한다.

.next()에 넘겨주는 값이 yield 부분 좌측의 변수에 할당이 된다.  그 원리를 이용해서 Promise 객체 인경우, Resolve됬을때 값을 보내서 fetchTodo에서 값을 받아볼수 있도록 만들수가 있다. 

 

async await을 쓰자.