Promise의 성질을 이용하여 다양한 응용을 할 수 있다.
시간초과 추가하기
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | const awaitTimeout = (delay) =>new Promise((resolve) => setTimeout(resolve, delay));
 
 awaitTimeout(300).then(() => console.log("Hi"));
 
 
 const f = async () => {
 await awaitTimeout(300);
 console.log("Hi");
 };
 
 | 
위의 코드는 delay를 받아서 delay 뒤에 resolve 하는 Promise로 래핑한 함수이다.
Promise.race를 이용하여 시간초과 로직을 추가할 수 있다.
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | const awaitTimeout = (delay, reason) =>new Promise(
 (resolve, reject) =>
 setTimeout(() => (reason === undefined ? resolve() : reject(reason))),
 delay
 );
 
 const wrapPromise = (promise, delay, reason) =>
 Promise.race([promise, awaitTimeout(delay, reason)]);
 
 wrapPromise(fetch("https://cool.api.io/data.json"), 3000, {
 reason: "Fetch timeout",
 })
 .then((data) => {
 console.log(data.message);
 })
 .catch((data) => console.log(`Failed with reason: ${data.reason}`));
 
 | 
promise.race는 가장 먼저 resolve된 데이터만을 사용하는 함수이다.
이러한 성질을 이용하여 delay안에 promise가 resolve되지 못할 시 에러를 발생시킨다.
시간초과를 위한 함수들을 하나의 객체로 정의하였다.
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 
 | class Timeout {constructor() {
 this.ids = [];
 }
 
 set = (delay, reason) =>
 new Promise((resolve, reject) => {
 const id = setTimeout(() => {
 if (reason === undefined) resolve();
 else reject(reason);
 this.clear(id);
 }, delay);
 this.ids.push(id);
 });
 
 wrap = (promise, delay, reason) =>
 Promise.race([promise, this.set(delay, reason)]);
 
 clear = (...ids) => {
 this.ids = this.ids.filter((id) => {
 if (ids.includes(id)) {
 clearTimeout(id);
 return false;
 }
 return true;
 });
 };
 }
 
 const myFunc = async () => {
 const timeout = new Timeout();
 const timeout2 = new Timeout();
 timeout.set(6000).then(() => console.log("Hello"));
 timeout2.set(4000).then(() => console.log("Hi"));
 timeout
 .wrap(fetch("https://cool.api.io/data.json"), 3000, {
 reason: "Fetch timeout",
 })
 .then((data) => {
 console.log(data.message);
 })
 .catch((data) => console.log(`Failed with reason: ${data.reason}`))
 .finally(() => timeout.clear(...timeout.ids));
 };
 
 | 
더욱 더 독립적으로 사용할 수 있게 되었다.
디바운싱
클로저와 Promise를 이용하여 디바운싱을 구현할 수 있다.
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | const debouncePromise = (fn, ms = 0) => {let timeoutId;
 const pending = [];
 return (...args) =>
 new Promise((res, rej) => {
 clearTimeout(timeoutId);
 timeoutId = setTimeout(() => {
 const currentPending = [...pending];
 pending.length = 0;
 Promise.resolve(fn.apply(this, args)).then(
 (data) => {
 currentPending.forEach(({ resolve }) => resolve(data));
 },
 (error) => {
 currentPending.forEach(({ reject }) => reject(error));
 }
 );
 }, ms);
 pending.push({ resolve: res, reject: rej });
 });
 };
 
 const fn = (arg) =>
 new Promise((resolve) => {
 setTimeout(resolve, 1000, ["resolved", arg]);
 });
 const debounced = debouncePromise(fn, 200);
 debounced("foo").then(console.log);
 debounced("bar").then(console.log);
 
 | 
위 코드는 ms 만큼의 delay 후에 마지막 호출의 값을 반환한다. 이전에 호출된 함수들은 마지막 호출과 동일한 데이터를 반환한다.
호출될 경우 외부 pending 배열을 복사한 후 이를 초기화한다.
ms동안 새로운 호출이 없을 경우 복사한 pending 배열을 순회하며 resolve나 reject를 호출한다.
Ref
How can I add a timeout to a promise in JavaScript?
Debounce promise
Promise
UsingPromise
debounce function implemented with promises