Skip to content

JavaScript:Promise

Promise는 비동기 작업의 최종 완료 또는 실패를 나타내는 객체입니다.

APIs

race

먼저 끝낸 Promise 를 반환한다.

reject

Promise.reject(reason) 메서드는 주어진 이유(reason)로 거부된 Promise 객체를 반환합니다.

Example:

Promise.reject("Testing static reject").then(function(reason) {
  // 호출되지 않음
}, function(reason) {
  console.log(reason); // "Testing static reject"
});

Promise.reject(new Error("fail")).then(function(error) {
  // 호출되지 않음
}, function(error) {
  console.log(error); // Stacktrace
});

오래된 콜백 API를 사용하여 Promise만들기

Promise는 생성자를 사용하여 처음부터 생성 될 수 있습니다. 이것은 오래된 API를 감쌀 때만 필요합니다.

이상적인 프로그래밍 세계에서는 모든 비동기 함수는 promise을 반환해야 하지만. 불행히도 일부 API는 여전히 success 및 / 또는 failure 콜백을 전달하는 방식일거라 생각합니다.. 예를 들면 setTimeout() 함수가 있습니다.

setTimeout(() => saySomething("10 seconds passed"), 10000);

예전 스타일의 콜백과 Promise를 합치는것 문제가 있습니다. 함수 saySomething()이 실패하거나 프로그래밍 오류가 있으면 아무 것도 잡아 내지 않습니다. setTimeout()의 문제점 입니다.

다행히도 우리는 setTimeout()을 Promise로 감쌀 수 있습니다. 가장 좋은 방법은 가능한 가장 낮은 수준에서 문제가되는 함수를 래핑 한 다음 다시는 직접 호출하지 않는 것입니다.

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);

기본적으로 promise constructor는 promise를 직접 해결하거나 reject 할 수 있는 실행자 함수를 사용합니다. setTimeout()은 함수에서 fail이 일어나거나 error가 발생하지 않기 때문에 이 경우 reject를 사용하지 않습니다.

Promise Timeout 만들기

결론부터 말하자면 다음의 순서로 진행하면 된다:

  1. 원래 수행할 작업을 Promise로 만든다.
  2. setTimeout에서 Exception을 내보내는 Promise를 만든다.
  3. 위의 두 Promise를 #race 함수로 호출한다.
  waitInitialized(timeout?: number) {
    const initPromise = this._initPromise.then((value: boolean) => {
      if (!value) {
        throw new Error();
      }
      return this.api;
    });

    if (typeof timeout !== 'undefined') {
      return initPromise;
    }

    const timeoutPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject(new TimeoutError('An initialization timeout occurred'));
      }, timeout);
    });
    return Promise.race([initPromise, timeoutPromise]);
  }

중첩 Promise

Jest를 사용하여 다음의 코드를 테스트하면 ...

describe('playground', () => {
  test('default', async () => {
    console.debug('BEGIN --');
    const aaa = new Promise((resolve, reject) => {
      setTimeout(() => {
        console.debug('resolve - before');
        resolve(1);
        console.debug('resolve - after');
      }, 1000);
    })
      .then(() => {
        console.debug('timeout done.');
      })
      .then(async () => {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            console.debug('[INSIDE] reject - before');
            reject('[INSIDE] reject call !');
            console.debug('[INSIDE] reject - after');
          }, 1000);
        })
          .then(() => {
            console.debug('[INSIDE] timeout done.');
          })
          .catch(error => {
            console.error(error);
          });
      })
      .then(() => {
        console.debug('next then');
      })
      .catch(error => {
        console.error(error);
      });
    console.debug('Promise.all ...');
    await Promise.all([aaa]);
    console.debug('END --');
  });
});

다음과 같은 결과가 나타난다.

BEGIN --
Promise.all ...
resolve - before
resolve - after
timeout done.
[INSIDE] reject - before
[INSIDE] reject - after
[INSIDE] reject call !
next then
END --

결론: 중첩으로 Promise 를 사용해도 결과가 잘 출력된다. 특히 14번째 줄의 async 함수를 사용해도 결국 Promise 의 재 중첩이 되므로 잘 실행된다.

See also

Favorite site