더 복잡한 상황이었지만 일반화한다면
main 모듈
-while문에 동기적인 작업을 반복한다.
-다른 모듈에 함수를 불러와서 사용하는데, 여기에 this에 프로퍼티를 수정하는 콜백함수를 넣어서 보낸다. (예시에서는 대체)
(사실 모듈이 나뉜다고 달라지는 건 없다.)
const test = async () => {
const callback = () => console.log("callback");
console.log("start");
while (1) {
await task(() => callback());
}
console.log("end");
};
test();
module.exports = async cb => {
return await setTimeout(res => {
cb();
}, 1000);
};
당연히 안된다. setTimerout은 async await를 붙인다고 promise를 객체를 반환하지 않는다. Timeout 객체를 반환한다.
결과는 당연히 한번도 응답받지 못하고 무한루프에서 함수 호출로 memory fault가 난다.
다른 모듈의 함수가 비동기적으로 호출된다는 것은 확인할 수 있다.
그렇다면 promise 객체를 반환시키면 어떨까?
module.exports = cb => {
return new Promise(res => {
setTimeout(res => {
cb();
res;
}, 1000);
});
};
일단, 위 함수는 res를 res()로 실행시키지 않았기 때문에 결과적으로 작동하지 않는다.
근데 뭔가 이상하다...
error 나는 것도 아니고, while문 바깥으로 끝난 것도 아니고, 콜백함수가 실행되고 그렇게 종료되버렸다..?
찾아보니
노드js는 timer나 네트워크 요청처럼 비동기 요청을 하면 ref 카운트를 한다. 이 카운트는 resolve가 호출되면 줄어드는데, 이벤트루프 종료시 이 카운트가 0 임에 따라 프로그램을 종료시킬지 결정한다고 한다.
프로미스 생성은 단순한 객체 생성으로 ref 카운트를 올리지는 않는다.
그렇다면 내 경우는 promise를 생성해 반환시켜, 그것을 참조 시키는 콜백이 없어(no pending callback) ref 카운트가 올라가지 않았고, timer는 무사히 작동해 종료되어 이벤트루프가 끝났을때 ref가 0이어서 nodeJS가 종료된 것이었다...
https://stackoverflow.com/questions/46966890/what-happens-when-a-promise-never-resolves
https://www.youtube.com/watch?v=PNa9OMajw9w
res를 실행 안힌 것도 문제였지만, 화살표 함수에 res를 인자로 넘겨도 undefined이다.(하여간ㅡㅡ) 클로저를 통해 res가 실행되야한다.
module.exports = cb => {
return new Promise(res => {
setTimeout(() => {
cb();
res();
}, 1000);
});
};
이로써, 프로미스 객체의 res를 기다리는 ref cnt가 올라가게 됨으로써 1초마다 callback을 반복적을 수행하게 되었다.
천신만고 끝에 구현했다고 할 수 있겠다....