TIL_72_Promise

JIEUN·2021년 4월 28일
0
post-thumbnail

자바스크립트 12. 프로미스 개념부터 활용까지 JavaScript Promise
위 영상을 기반으로 작성하였음.

2초 후에 'ellie' 가 출력된다.

resolve 를 주석처리하고 reject 를 추가하였더니 2초 후에 Error: no network 가 출력된 것을 확인할 수 있다.


.catch를 추가하여 Error를 다룰 수 있다.





.catch 를 통해 error가 발생했을 때 '🥖'으로 대체하여 cook 까지 도달할 수 있도록 했다.

.catch 부분을 주석처리 했더니 계란 프라이가 되지 못한 채 egg 부분에서 멈춘 것을 확인할 수 있다.

'use strict';
//Promise is a JavaScript object for asynchronous operation.
// State: pending -> fulfilled or rejected
// Producer 와 Consumer

// 1. Producer
// when new Promise is created, the executor runs automatically.
const promise = new Promise((resolve, reject) => {
  //doing some heavy work (network, read files)
  console.log('doing something...');
  setTimeout(() => {
    resolve('ellie');
    //reject(new Error('no network'));
  }, 2000);
});

//2. Consumers: then, catch, finally
promise.then((value) => {
  console.log(value);
})
.catch(error => {
  console.log(error);
})
.finally(() => {
  console.log('finally');
})
//성공과 실패에 상관없이 어떤 기능을 마지막으로 수행하고 싶을 때 사용할 수 있음.

아래는 지난 번에 만들었던 콜백지옥이다. promise를 통해 이 콜백지옥을 수정해보자.

// Callback Hell example

class UserStorage {
  loginUser(id, password, onSuccess, onError) {
    setTimeout(() => {
      if (
      (id === 'ellie' && password === 'dream') ||       (id === 'coder' && password === 'academy')
     ) {
        onSuccess(id);
      } else {
        onError (new Error('not found'));
      }
    }, 2000);
  }
  
  getRoles(user, onSuccess, onError) {
    setTimeout(() => {
      if (user === 'ellie') {
        onSuccess({ name: 'ellie', role: 'admin'});
      } else {
        onError(new Error('no access'));
      }
    }, 1000);
  }
}

const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
  id,
  password,
  user => {
    userStorage.getRoles(
      user,
      userWithRole => {
        alert(
          `Hello ${userWithRole.name}, you have a ${userWithRole.role} role`
    );
  },
  error => {
    console.log(error);
  }
  );
},
error => {
  console.log(error);
})

아래 코드로 수정이 되었따.

// Callback Hell example
class UserStorage {
  loginUser(id, password) {
    return new Promise((resolve, reject) => {
       setTimeout(() => {
      if (
      (id === 'ellie' && password === 'dream') || 
      (id === 'coder' && password === 'academy')
     ) {
        resolve(id);
      } else {
        reject(new Error('not found'));
      }
    }, 2000);
    });
  }
  
  getRoles(user) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (user === 'ellie') {
          resolve({ name: 'ellie', role: 'admin' });
        } else {
          reject(new Error('no access'));
        }
      }, 1000);
    });
  }
}

const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');

userStorage.loginUser(id, password)
.then(user => userStorage.getRoles)
// .then(userStorage.getRoles)로 생략가능
.then(user => alert(`Hello ${user.name}, 
you have a ${user.role} role`))
.catch(console.log);

프로미스 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과값을 나타냄.

프로미스를 사용하면 비동기 메소드를 동기 메소드처럼 값을 반환할 수 있다.
다만, 최종 결과를 반환하지는 않고 프로미스를 반환해서 미래의 어떤 시점에 결과를 제공한다.

프로미스가 가지는 상태들
1. 대기 (pending): 이행하거나 거부되지 않은 초기상태.
2. 이행 (fulfilled): 연산이 성공적으로 완료.
3. 거부 (rejected): 연산이 실패.

대기 중인 프로미스는 값과 함께 이행될수도, 어떤 오류로 인해 거부될 수도 있다.
이행이나 거부일 때, 프로미스에 연결한 처리기는 그 프로미스의 then 메소드에 의해 대기열에 오른다.

  1. 대기 (pending)
new Promise();
new Promise(function(resolve, reject) {
  // ...
});

new Promise() 메소드를 호출할 때, 콜백함수를 선언할 수 있고 콜백함수의 인자는 resolve, reject 이다.

  1. 이행 (fulfilled)
new Promise(function(resolve, reject) {
  resolve();
});

콜백 함수의 인자 resolve를 실행하면 이행 상태가 된다.

function getData() {
  return new Promise(function(resolve, reject) {
    var data = 100;
    resolve(data);
  });
}

// resolve()의 결과 값 data를 resolveData로 받음
getData().then(function(resolvedData) {
  console.log(resolvedData); //100
});

이행 상태가 되려면 위 코드와 같이 then()을 이용하여 처리 결과값을 받을 수 있다.

  1. 거부 (rejected)
new Promise(function(resolve, reject) {
  reject();
});

reject를 호출하면 실패 상태가 됨.

function getData() {
  return new Promise(function(resolve, reject) {
    reject(new Error("Request is failed"));
  });
}

// reject() 의 결과 값 Error를 err에 받음
getData().then.catch(function(err) {
  console.log(err); //Error: Request is failed
});

실패 상태가 되면 실패한 이유 (실패 처리의 결과 값)를 catch()로 받을 수 있다.

프로미스의 메소드들
1. promise.prototype.catch()

프로미스에 거부 처리기 콜백을 추가하고 호출된 경우 콜백의 반환값 또는 프로미스가 대신 이행된 경우 그 원래 이행(fulfillment)값으로 결정하는(resolving) 새 프로미스를 반환.

2. promise.prototype.then()

프로미스에 이행 또는 거부 처리기를 추가하고 호출된 처리기의 반환값 또는 프로미스가 처리되지 않은 경우 그 원래 처리된(settled) 값으로 결정하는 새 프로미스를 반환.

3. promise.prototype.finally()

0개의 댓글