[TIL] promise

정세비·2021년 5월 23일
0

JavaScript

목록 보기
11/16
post-thumbnail

callback을 많이 사용하면 아래와 같은 문제점이 있다.

  • 가독성이 떨어짐
  • 에러가 발생하거나 디버깅을 발생했을 때 해결도 어려움
  • 유지보수도 어려움
    이를 해결하기 위해 promise를 사용해볼 수 있다.

promise

  • JS에서 제공하는 비동기를 간편하게 처리할 수 있도록 도와주는 object
  • promise는 정해진 장시간의 기능이 수행되고 나서 정상적으로 기능이 수행되었다면 성공메세지와 함께 결과값을 전송하고, 문제가 생기면 error를 전달함

1 state

  • pending : promise가 만들어져서 우리가 지정한 operation이 수행중일 때
  • fulfilled : 성공적으로 끝낼 때
  • rejected : 파일을 찾을 수 없거나, 네트워크에 문제가 있을 때

원하는 기능을 수행해서 해당하는 데이터를 만들어내는 producer, 즉 promise object
원하는 데이터를 소비하는 consumer

2 producer, consumer

  • producer : 원하는 기능을 수행해서 해당하는 데이터를 만들어 냄
  • consumer : 원하는 데이터를 소비

(2-1) producer

  • promise는 class기 때문에 new라는 키워드를 이용해서 object를 생성
    • 네트워크 통신이나 파일을 읽어오는 것은 heavy한 work이기 때문에 promise를 이용하여 비동기적으로 처리하는 것이 효율적
  • promise는 생성되자마자 executor를 자동적으로 실행함
const promise = new Promise((resolve, reject) => {
  console.log('hi');
});

setTimeout()으로 2초의 delay를 줘보자.
기능 수행이 정상적으로 되었을 경우 resolve 콜백함수를 호출하고, 값으로 'wow'를 전달하는 코드를 짜보면

const promise = new Promise((resolve, reject) =< {
  console.log('hi');
  setTimeout(() => {
    resolve('wow');
  }, 2000);
});

💡 주의 💡
promise를 만드는 순간 우리가 전달한 executer라는 callback 함수가 바로 실행됨
이 말은, promise 내에 네트워크 통신을 하는 코드를 작성했다면, promise가 만들어지는 순간 네트워크 통신을 수행하게 되는 것을 의미한다.
따라서 만약 사용자가 요구했을 때만 네트워크 통신을 수행해야 한다면(예: 버튼 누른 후 실행) promise 사용은 지양해야 한다


(2-2) consumer

then : promie가 정상적으로 수행될 때

  • 고차함수(higher-order-function)이며 2개의 콜백함수를 인수로 가진다.
  • 이러한 콜백을 handler라고 부르며, promise가 settles되면, settled value로 적절한 handler가 호출된다.
  • onFulfilled과 onRejected라는 핸들러를 가지며 각자 resolve와 reject에 대한 로직을 포함한다.
let prom = new Promise((resolve, reject) => {
let num = Math.random();
if (num < .5 ){
  resolve('Yay!');
} else {
  reject('Ohhh noooo!');
}
});

const handleSuccess = (resolvedValue) => {
console.log(resolvedValue);
};

const handleFailure = (rejectionReason) => {
console.log(rejectionReason);
};

prom.then(handleSuccess, handleFailure);

then은 promise가 정상적으로 잘 수행이 되어서 마지막에 최종적으로 resolve 콜백함수의 값이 value라는 parameter로 전달되어져 들어오는 것을 볼 수 있다.

then은 값을 전달할 수도 있고, 또 다른 비동기인 promise를 전달할 수도 있다


catch : promise가 reject됐을 때
finally : 성공이나 실패에 상관없이 무조건 마지막에 호출됨

resolve 대신 reject를 호출해볼 때!

  • reject는 보통 error라는 object를 통해서 값을 전달한다
  • error라는 class는 JS에서 제공하는 object 중 하나이다
  • error를 작성할 땐 어떤 에러가 발생했는지 이유를 잘 명시해서 작성해야 함

(2-1) producer

const promise = new Promise((resolve, reject ) => {
    alert('hi');
    setTimeout(() => {
       reject(new Error('no network'));
    }, 2000);
  });

<결과>

(2-2) consumer

error handling하는 법
catch()를 이용

promise
.then(value => {
    alert(value);
  })
.catch(error => {
    alert(error);
});



3. promise chaining

const calculate = new Promise ((resolve, reject) => {
    setTimeout(() => resolve(10), 1000);
});

calculate
 .then(num => num / 5)  // 2
.then(num => num * 3)  // 6
.then(num => {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(num / 2), 1000) //3
    });
})
.then(num => console.log(num)); // 2초 후 3 이 나옴

위에서 볼 수 있듯이
.then을 여러번 묶어서 처리할 수 있음
또한 .then은 값을 전달해도 하고, 또다른 비동기 promise를 전달해도 되는 것을 알 수 있다.

이 때 주의해야할 점은
return을 잊지않고 꼭 적어줘야한다는 점이다.!


<연습> 선글라스 주문하기

We’re going to create a promise representing ordering sunglasses from an online store. First, create the function, myExecutor(). Later on, you’ll pass this function into the Promise constructor.


myExecutor() should:

  • Have two parameters: resolve and reject
  • Check if the sunglasses property on the inventory object has a value greater than zero
  • If it does, myExecutor() should invoke resolve() with the string 'Sunglasses order processed.'
  • If it does not, myExecutor() should invoke reject() with the string 'That item is sold out.'

  1. Create a function, orderSunglasses(). This function should have no parameters. It should return a new promise constructed by passing your myExecutor() function into the Promise constructor.
  2. Create a variable orderPromise assigned to the returned value of your orderSunglasses() function.
  3. At the bottom of your app.js file, log orderPromise to the console.
const inventory = {
  sunglasses: 1900,
  pants: 1088,
  bags: 1344
};


const myExecutor = (resolve, reject) => {
  if(inventory.sunglasses > 0) {
    resolve'Sunglasses order processed.');
  } else {
    reject('That item is sold out.');
  }
};

const orderSunglasses = () => {
  return new Promise(myExecutor);
};

const orderPromise = orderSunglasses();

console.log(orderPromise);

// Promise { 'Sunglasses order processed.' }

Review

  • Promises are JavaScript objects that represent the eventual result of an asynchronous operation.
  • Promises can be in one of three states: pending, resolved, or rejected.
  • A promise is settled if it is either resolved or rejected.
  • We construct a promise by using the new keyword and passing an executor function to the Promise constructor method.
  • setTimeout() is a Node function which delays the execution of a callback function using the event-loop.
  • We use .then() with a success handler callback containing the logic for what should happen if a promise resolves.
  • We use .catch() with a failure handler callback containing the logic for what should happen if a promise rejects.
  • Promise composition enables us to write complex, asynchronous code that’s still readable. We do this by chaining multiple .then()‘s and .catch()‘s.
    To use promise composition correctly, we have to remember to return promises constructed within a .then().
    We should chain multiple promises rather than nesting them.
    To take advantage of concurrency, we can use Promise.all().
profile
파주

0개의 댓글