본문 바로가기

Frontend

[번역] JavaScript Promises: an introduction

 

JavaScript Promises: 소개

Promise는 지연 및 비동기 계산을 단순화합니다. Promise는 아직 완료되지 않은 작업을 나타냅니다.

web.dev

프로미스는 지연(deferred) 및 비동기 연산을 간소화한다. 프로미스는 아직 완료되지 않은 연산을 나타낸다.

-> 비동기 처리의 상태(pending, fulfilled..)와 결과를 나타내는 객체

 

개발자 여러분, 웹 개발의 역사에서 중요한 순간을 맞이할 준비를 하세요. 자바스크립트에 Promise가 생겼습니다!

Browser support and polyfill

완전한 프로미스 구현이 없는 브라우저 사양을 준수하도록 만들거나 다른 브라우저 및 Node.js에 프로미스를 추가하려면 폴리필을 확인하세요.

What's all the fuss about?

자바스크립트는 싱글스레드이므로 두 가지의 스크립트를 동시에 실행할 수 없으며 차례대로 실행해야 합니다. 브라우저에서 자바스크립트는 브라우저마다 다른 여러 가지 작업과 스레드를 공유합니다. 하지만 일반적으로 자바스크립트는 페인팅, 스타일 업데이트, 사용자 작업(텍스트 강조 표시 및 폼 컨트롤 상호작용 등) 처리와 같은 대기열에 있습니다. 이 중 하나의 작업이 지연되면 다른 작업이 지연됩니다.

 

인간은 멀티스레드입니다. 여러 손가락으로 타이핑할 수 있고, 운전을 하면서 동시에 대화를 나눌 수 있습니다. 우리가 처리해야 하는 유일한 차단 기능은 재채기인데 재치기하는 동안 모든 현재 활동을 일시 중단해야 합니다. 특히 운전 중에 대화를 나누려고 할 때 꽤 성가신 일입니다. 당신은 재채기를 유발하는 코드를 작성하고 싶지 않을 것입니다. 

 

당신은 이 문제를 해결하기 위해 이벤트와 콜백을 사용해 본 적이 있을 것입니다. 다음은 이벤트입니다.

 

var img1 = document.querySelector('.img-1');

img1.addEventListener('load', function() {
  // woo yey image loaded
});

img1.addEventListener('error', function() {
  // argh everything's broken
});

 

이것은 전혀 재채기가 아닙니다. 이미지를 가져와서 리스너 몇 개를 추가하면 리스너 중 하나가 호출될 때까지 자바스크립트가 실행을 중지할 수 있습니다. 안타깝게도 위의 예제에서는 이벤트를 수신하기 전에 이벤트가 발생했을 가능성이 있으므로 이미지의 '완료' 속성을 사용하여 이 문제를 해결해야 합니다.

 

var img1 = document.querySelector('.img-1');

function loaded() {
  // woo yey image loaded
}

if (img1.complete) {
  loaded();
}
else {
  img1.addEventListener('load', loaded);
}

img1.addEventListener('error', function() {
  // argh everything's broken
});

 

안타깝게도 DOM에서는 이를 수행할 수 있는 방법을 제공하지 않기 때문에 오류가 발생한 이미지를 잡아내지 못합니다. 또한 이것은 하나의 이미지를 로드하는 것입니다. 이미지 세트가 언제 로드되었는지 알고 싶다면 상황은 더 복잡해집니다. 

Events aren't always the best way

이벤트는 keyup, touch 시작 등 동일한 객체에서 여러 번 일어날 수 있는 일에 유용합니다. 이러한 이벤트를 사용하면 리스너를 연결하기 전에 무슨 일이 일어났는지는 신경 쓰지 않아도 됩니다. 하지만 비동기 성공 / 실패에 관해서는 이상적으로 다음과 같은 것을 원합니다:

 

img1.callThisIfLoadedOrWhenLoaded(function() {
  // loaded
}).orIfFailedCallThis(function() {
  // failed
});

// and…
whenAllTheseHaveLoaded([img1, img2]).callThis(function() {
  // all loaded
}).orIfSomeFailedCallThis(function() {
  // one or more failed
});

 

이것이 바로 프로미스가 하는 일이지만, 더 나은 이름을 붙이면 됩니다. HTML 이미지 요소에 프로미스를 반환하는 'ready' 메서드가 있었다면 이렇게 할 수 있었을 것 입니다:

 

img1.ready()
.then(function() {
  // loaded
}, function() {
  // failed
});

// and…
Promise.all([img1.ready(), img2.ready()])
.then(function() {
  // all loaded
}, function() {
  // one or more failed
});

 

가장 기본적으로 Promise는 이벤트 리스너와 비슷하지만 다른 점이 있습니다.

 

- 프로미스는 한 번만 성공하거나 실패할 수 있습니다. 두 번 성공하거나 실패할 수 없으며, 성공에서 실패로 또는 그 반대로 전환할 수도 없습니다.

- 프로미스가 성공 또는 실패한 후 나중에 성공/실패 콜백을 추가하면 이벤트가 이전에 발생했더라도 올바른 콜백이 호출됩니다.

 

이는 비동기 성공 / 실패에 매우 유용한데, 이는 무언가를 사용할 수 있게 된 정확한 시간에는 관심이 없고 결과에 반응하는데 더 관심이 있기 때문입니다. 

Promise terminology

프로미스는 다음과 같은 상태가 될 수 있다.

- fulfilled: the action relating to the promise succeeded

- rejected: the action relating to the promise failed

- pending: Hasn't fulfilled or rejected yet

- settled: Has fulfilled or rejected

 

스펙에서 또한 프로미스와 비슷한 객체를 설명할 때 thenable이라는 용어를 사용합니다.

Promises arrive in JavaScript!

프로미스 구현은 표준화된 동작을 따르지만 전반적인 API는 다릅니다. 자바스크립트 프로미스는 RSVP.js와 API가 유사합니다. 다음은 프로미스를 만드는 방법입니다:

 

var promise = new Promise(function(resolve, reject) {
  // do a thing, possibly async, then…

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

 

프로미스 생성자는 하나의 인자, 두 개의 매개변수가 있는 콜백, resolve와 reject를 받습니다. 콜백 내에서 비동기 방식으로 무언가를 수행한 다음 모든 것이 작동하면 resolve를 호출하고 그렇지 않으면 reject를 호출합니다. 

 

일반 자바스크립트에서 throw와 마찬가지로 Error 객체를 사용하여 reject하는 것이 일반적이지만 필수는 아닙니다. Error 객체의 장점은 스택 추적을 캡처하여 디버깅 도구를 더욱 유용하게 만든다는 점입니다. (Like throw in plain old JavaScript, it's customary, but not required, to reject with an Error object. The benefit of Error objects is they capture a stack trace, making debugging tools more helpful.)

 

이 프로미스를 사용하는 방법은 다음과 같습니다.

 

promise.then(function(result) {
  console.log(result); // "Stuff worked!"
}, function(err) {
  console.log(err); // Error: "It broke"
});

 

then()은 성공 케이스에 대한 콜백, 실패 케이스에 대한 콜백 두 개의 인수를 받습니다. 둘 다 선택 사항이므로 성공 또는 실패 사례에 대해서만 콜백을 추가할 수 있습니다.

 

자바스크립트 프로미스는 DOM에서 Future로 시작하여 Promise로 이름이 바뀌었고 마침내 자바스크립트로 옮겨졌습니다. DOM이 아닌 JavaScript에 있는 것이 좋은 이유는 Node.js와 같은 비브라우저 JS 컨텍스트에서 사용할 수 있기 때문입니다.

 

프로미스는 자바스크립트의 기능이지만 DOM은 이를 사용하는 것을 두려워하지 않습니다. 실제로 비동기 성공 / 실패가 있는 모든 새로운 DOM API는 프로미스를 사용합니다.  이미 할당량 관리, 글꼴 로드 이벤트, ServiceWorker, Web MIDI, Streams등에서 이러한 현상이 일어나고 있습니다.

'Frontend' 카테고리의 다른 글

[번역] The BFF Pattern: An Introduction  (0) 2023.04.18
Why React isn't dying  (0) 2023.03.29
Prop Drilling  (0) 2023.03.16
프레임워크 없는 프론트엔드 개발 | 렌더링  (0) 2023.03.12
[번역] Widget Driven Development  (0) 2023.03.11