Delaying of Function2023/04/11

Preview


JS로 개발하다 보면 비동기 처리에 항상 신경을 쓸 수밖에 없습니다.

Methodology

만약 얼마나 걸릴지 알수없는 함수 longTimeFunc(Function) 가 있고 그 함수를 호출해야 하는 함수는 오래 걸리는 메서드의 프로세스가 끝난 뒤에 결과 값을 출력해야 하는 경우라면 어떻게 해야 할까요?

1const RandomTimeSec = parseInt(Math.random() * 10); 2 3const longTimeFunc = () => { 4 setTimeout(() => { 5 console.log(RandomTimeSec + "초만큼 걸렸네요"); 6 }, RandomTimeSec * 1000); 7}; 8 9const originalFunc = () => { 10 longTimeFunc(); 11 console.log("originalFunc 끝났습니다."); 12}; 13 14originalFunc();
1//result 2originalFunc 끝났습니다. 36초만큼 걸렸네요

originalFunc 끝났습니다가 나중에 찍혀야 한다면..

Callback

1const RandomTimeSec = parseInt(Math.random() * 10); 2 3const longTimeFunc = (callback) => { 4 setTimeout(() => { 5 console.log(RandomTimeSec + "초만큼 걸렸네요"); 6 callback(); 7 }, RandomTimeSec * 1000); 8}; 9 10const originalFunc = () => { 11 const printResult = () => { 12 console.log("originalFunc 끝났습니다."); 13 }; 14 longTimeFunc(printResult); 15}; 16 17originalFunc();
16초만큼 걸렸네요 2originalFunc 끝났습니다.

가장 Basic 한 방법입니다.

나중에 실행해야 하는 로직을 callback 함수에 담아 보내고 longTimeFunc이 다 끝나면 해당 함수를 실행시킵니다.

다만, callback함수를 쓰는 것은 실행해야 할 함수가 많아지면 어떤 게 어떤 함수의 callback 인지 헷갈리는 경우가 있기 때문에 가독성이 떨어집니다.

Callback 을 사용하는 방법도 다양합니다. new Promise, async await 를 사용할 수도 있습니다.

1/*new Promise 사용하기*/ 2const RandomTimeSec = parseInt(Math.random() * 10); 3 4const longTimeFunc = (callback) => { 5 setTimeout(() => { 6 console.log(RandomTimeSec + "초만큼 걸렸네요"); 7 callback(); 8 }, RandomTimeSec * 1000); 9}; 10 11const originalFunc = () => { 12 console.log("originalFunc 끝났습니다."); 13}; 14 15new Promise((resolve) => { 16 longTimeFunc(resolve); 17}).then(() => { 18 originalFunc(); 19});
13초만큼 걸렸네요 2originalFunc 끝났습니다.

new Promise then을 사용하면 로직자체가 한눈에 들어옵니다. 하지만 더 한눈에 들어오게 하는 방법이 있습니다.

1/*async await 사용하기 */ 2const RandomTimeSec = parseInt(Math.random() * 10); 3 4const longTimeFunc = () => { 5 return new Promise((resolve) => { 6 setTimeout(() => { 7 console.log(RandomTimeSec + "초만큼 걸렸네요"); 8 resolve(); 9 }, RandomTimeSec * 1000); 10 }); 11}; 12const originalFunc = async () => { 13 await longTimeFunc(); 14 console.log("originalFunc 끝났습니다."); 15}; 16 17originalFunc();

async await 를 쓰면 await이라는 단어 때문인지 어떤 함수를 기다리고 어떤 절차로 진행되는지 파악하기가 더 쉬워집니다.

new Promise 안에 resolve 는 한 가지 비밀이 있는데 다음 실행해야 할 함수에 첫 번째 파라미터만 전달할 수 있습니다.

1const RandomTimeSec = parseInt(Math.random() * 10); 2 3const longTimeFunc = () => { 4 return new Promise((resolve) => { 5 setTimeout(() => { 6 console.log(RandomTimeSec + "초만큼 걸렸네요"); 7 resolve(1, 2); 8 }, RandomTimeSec * 1000); 9 }); 10}; 11const originalFunc = async () => { 12 let result = await longTimeFunc(); 13 console.log(result); 14}; 15 16originalFunc();
18초만큼 걸렸네요

만약 longTimeFunc에서 여러 개의 값을 return 해야 하는 상황이 온다면 배열에 담거나 object에 담아 resolve로 보내야 합니다.

1/*async await 사용하기 */ 2const RandomTimeSec = parseInt(Math.random() * 10); 3 4const longTimeFunc = () => { 5 return new Promise((resolve) => { 6 setTimeout(() => { 7 console.log(RandomTimeSec + "초만큼 걸렸네요"); 8 resolve({ first: 1, second: 2 }); 9 }, RandomTimeSec * 1000); 10 }); 11}; 12const originalFunc = async () => { 13 let result = await longTimeFunc(); 14 console.log(result); 15}; 16 17originalFunc();
12초만큼 걸렸네요 2{ first: 1, second: 2 }

The End


여러 가지 방법이 있지만 혼자만 개발하는 것이 아니니 최대한 다른 사람이 보기에도 한 눈에 읽히는 코드를 짜야하는걸 매번 느낍니다. 더 Clean 한 코드를 짜는 날까지!