yngmanie 블로그

promise란? (1)

해당 포스트는 Master the JavaScript Interview: What is a Promise?을 번역하여 작성하였습니다. 잘못된 부분이 있다면 댓글 부탁드립니다.

promise란?

promise는 미래에 싱글 값을 생성하는 객체입니다. 해결된 값이나 네트워크 에러와 같이 해결되지않은 값 모두를 생성합니다. promise는 ulfilled, rejected, pending와 같이 3가지의 상태 중 하나 일 수 있습니다. promise 사용자는 콜백으로 fulfilled 값이나 거절에대한 이유를 핸들링할 수 있습니다.

promise constructor가 실행되는 즉시 promise는 주어진 일을 처리할 할 수 있습니다. 만약 처리하는 속도를 지연시키기 위해서는 observavlestasks를 참고 부탁드립니다.

promise에 불완전한 히스토리

1980년대 초 MultiLisp와 Concurrent Prolog와 같은 언어로 promise의 구현은 시작되었고 promise라는 단어는 1988년 Barbara Liskov에 의해 사용되기 시작했습니다.

필자가 javascript에서 promise를 처음들었을 때는 Node가 새롭게 구현되었고 커뮤니티에서 비통기를 핸들링하는 최적의 방법에 대해서 논의를 하던 중 이었습니다. 커뮤티니에서 promise에 대한 실험을 동안 Node는 error-first 콜백을 표준으로 삼았습니다.

같은 시간에 Dojo는 promise를 Deferred API로 추가했습니다. 하지만 promise에 대한 관심과 활동으로 상호작용 가능하고 추가된 기능의 promise를 만들게 됩니다.

jQuery의 비동기 동작은 promise을 바탕으로 리팩토링한 것입니다. jQuery의 promise 지원은 Dojo’의 Deferred와 매우 비슷하고, jQuery의 대중성 덕분에 javascript에서 promise가 일반적인 통신방법으로 자리잡았습니다. 그러나 한 동안 fulfilled 및 rejected 그리고 예외 처리를 위해 promise위에 툴을 만드는 것이 지원되지 않았습니다.

이런 취약점에도 불구하고 jQuery는 javascript promise를 주류로 만들었으며 promise 라이브러리인 Q, When, Bluebird가 인기를 얻는데 큰 공헌을 했습니다. jQuery 구현의 비호환성은 promise 스펙에 몇 가지 중요한 설명에 동기부여가 됐습니다. 그것은 재작성 및 promises/A+ specification으로 이름을 변경하였습니다.

ES6는 promise/A+가 promise 글로벌 표준으로 삼도록 했으며, 특히 WHATWG Fetch스펙과 비동기 함수표준과 같이 중요한 API는 새로운 promise 표준에 등록되었습니다.

여기서 묘사된 promise는 Promise/A+ 스펙과 호환이되고 ECMAScript 표준 구현에 초첨이 맞춰져 있습니다.

promise는 어떻게 동작할까요?

promise는 비동기 함수로부터 동기로 값을 리턴하는 객체입니다. 그것은 3가지 상태중에 하나입니다.

  • Fulfilled: onFulfilled()가 호출됩니다.(예를 들어, resolve()로 불립니다.)
  • Rejected: onRejected()가 호출됩니다.(예를 들어, reject()가 호출됩니다.)
  • Pending: fulfiled나 rejected가 아닌 경우입니다.

promise는 pending이 아닌 이상 안정적입니다. 때로 사람들은 resolved와 settled를 동일하다고 간주합니다.

일단 settled가 되면, promise는 resettled가 될 수 없습니다. resolve()나 reject()를 다시 호출해도 효과가 없습니다. 변경 불가능한 setted promise는 중요한 특징입니다.

순수 javascript promise는 promise 상태를 노출하지 않습니다. 대신 promise를 볼 수 없는 것으로 생각해야합니다. promise를 생성한 함수만이 promise의 상태를 알고 있고 resolve와 reject으로 접근할 수 있습니다.

여기 특정시간이 지난 후에 resolve하고 promise를 리턴하는 함수가 있습니다.

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

wait(3000).then(() => conosle.log("안녕")); // 안녕

wait(3000)은 3초후에 호출되며, “안녕”이라는 로그를 표시할 겁니다. 모든 호환 가능한 promise는 resolved나 rejected의 값을 가질수 있는 핸들러를 사용할 수 있도록 .then() 메소드를 제공합니다.

ES6 promise 생성자는 함수를 가질 수 있습니다. 그 함수는 resolve()와 reject() 2개의 파라미터를 가지고 있습니다. 위에 예시에서 우리는 resolve()만 사용했습니다. 그리고 우리는 resolve() 호출을 딜레이하기 위해 setTimeout()을 호출했습니다.

.then()에 콜백함수로 전달될 resolve()와 reject()는 선택적으로 사용될 수 있습니다.

reject()을 사용할 때 Error 객체를 전달합니다. 일반적으로 정상적이거나 예외적인 경우의 상태를 원합니다. Error객체로 그것을 명시적으로 확인할 수 있습니다.

중요한 promise 룰

promise 표준은 promises/A+ specification에 명시되어 있습니다. 그 안에는 javascript 표준과 ESMASript promise를 포함해 구현에 따르는 많은 내용이 있습니다.

promise는 아래의 특정한 룰은 반드시 따르고 있습니다.

  • promise와 “thenable”은 .then()메소드를 제공하는 객체입니다.

  • pending은 fulfiled 혹은 rejected 상태로 변경됩니다.

  • fulfiled 혹은 rejected된 promise는 고정적이고 상태가 변경되지 않습니다.

  • promise의 상태가 정해지면 반드시 값을 가지고 있고(undefined도 상관없음) 그 값은 변하지 않습니다.

이 컨텍스트에서 변경되는거는 === 식별자를 비교하는 것을 참조합니다. 객체가 fulfilled 된 값으로 사용될 수 있으며 객체 속성이 변경 될 수 있습니다.

모든 promise는 아래와 같이 .then() 메소드를 제공합니다.

promise.then(
  onFulfilled?: Function,
  onRejected?: Function
) => Promise

.then()메소드는 아래의 룰을 반드시 준수합니다.

  • onFulfilled()와 onRejected()는 선택적입니다.
  • 인수가 함수가 아니면 무시됩니다.
  • onFulfiled()는 promise가 거절된 후에 호출되며 첫 번재 인수로 거절된 이유가 반환됩니다. 그 이유는 유효한 javascript 값이지만 Error객체를 사용하는 것을 추천합니다.
  • onFulfilled()와 onRejected() 모두 한 번 이상 호출되지 않습니다.
  • .then()은 같은 promise에서 여러번 호출될 수 있습니다. 즉, 콜백함수의 집합이라고 할 수 있습니다.
  • .then()은 반드시 새로운 promise를 리턴합니다.
  • 만약 onFulfilled()와 onRejected()가 x를 리턴하고 그것이 promise라면 promise2는 x로 고정됩니다. 그렇지 않으면 promise2는 x에 fulfiled 됩니다.
  • 만약 onFulfilled()와 onRejected()가 e를 throw한다면 promise2sms promise1과 동일한 값으로 충족됩니다.
  • onRejected가 함수고 아니고 promise1이 거절된다면 promise2는 promise1과 같은 이유로 거절됩니다.

»> promise란?(2) 바로가기