Promise, Async & Await

Judo·2020년 12월 21일
1

비동기 처리를 위해 callback, Promise, Async & Await을 사용한다.

질문


Promise 실행함수가 가지고 있는 두 개의 파라미터, resolve, reject는 각각 무엇을 의미하나요?

- `executor`는 `resolve` 및 `reject` 인수를 전달할 실행함수.
- `executor`는 보통 비동기 작업을 실행한 후 모든 작업을 끝내면 `resolve`를 호출해 프로미스를 이행, 오류가 발생한 경우 `reject`를 호출해 거부한다.
- JS가 자체적으로 생성하는 콜백임
  • resolve, reject함수에는 인자를 넘길 수 있습니다. 이때 넘기는 인자는 어떻게 사용할 수 있나요?
    • 프로미스에서 resolve(arg)가 실행될 경우
      .then(arg)를 이용해 인자를 받을 수 있다.
    • 프로미스에서 reject(arg)가 실행될 경우
      .then().catch(arg)를 이용해 인자를 받을 수 있다.

new Promise()를 통해 생성한 Promise 인스턴스에는 어떤 메소드가 존재하나요? 각각은 어떤 용도인가요?

  • catch()
    • 프로미스가 거부된다면 catch()가 호출되고 콜백의 반환값을 받을 수 있다.
  • then()
    • 프로미스가 이행된다면 then을 이용해 반환값을 이용할 수 있고 새 프로미스를 반환할 수도 있다..
  • finally()
    • 프로미스 이행 여부에 관계없이 무조건 호출된다.

Promise 생성자 함수에 들어있는 메소드는?

  • Promise.all(iterable)
    • iterable이 프로미스인 경우 이행된 값들을 반환하는 대기 중인 Promise를 반환한다. 즉, iterable이 이행될 때까지 기다렸다가 다 이행되면 대기중인 Promise를 반환함.
    • 주어진 프로미스 중 하나라도 거부하면, 다른 프로미스의 이행 여부에 상관없이 첫 번째 거부 이유를 사용해 거부. 즉, 거부가 있다면 다른 프로미스는 제외시킴
  • Promise.race(iterable)
    • iterable에서 먼저 이행되거나 거부된 프로미스의 값을 갖고 있는 대기 중인 프로미스. 가장 빠르게 완료된 값을 갖고 있다고 생각하면 된다.
  • Promise.reject()
    • 주어진 이유로 거부하는 Promise 객체 반환
  • Promise.resolve()
    • 주어진 값으로 이행되는 Promise 객체 반환
  • pending

Promise.prototype.then 메소드는 무엇을 리턴하나요?

  • then은 두 가지 매개변수를 갖고 있다.
  • Promise가 수행될 때 호출되는 onFulfilled
  • 이행 값 하나를 인수로 받는다.
  • Promise가 거부될 때 호출되는 onRejected
  • 거부 이유 하나를 인수로 받는다.
	...then((data, error) => {
    })

Promise.prototype.catch 메소드는 무엇을 리턴하나요?

  • promise를 리턴한다. 사실 catch 내부적으로 Promise.prototype.then(undefined, onRejected)를 호출한다. 그리고 호출한 then의 반환값인 Promise를 리턴한다.

Promise의 세가지 상태는 각각 무엇이며, 어떤 의미를 가지나요?

- Pending: 이행되거나 거부되지 않은 초기 상태
- Fulfilled: 연산이 성공적으로 완료됨.
- rejected: 연산이 실패함

await 키워드 다음에 등장하는 함수 실행은, 어떤 타입을 리턴할 경우에만 의미가 있나요?

  • Promise 타입을 리턴한 경우에만 의미가 있다.
  • awaitPromisefulfill 되거나 reject 될 때까지 async 함수의 실행을 일시 정지하고, Promisefulfill되면 async 함수를 일시 정지한 부분부터 실행합니다.

await 키워드를 사용할 경우, 어떤 값이 리턴되나요?

  • Promise 에서 fulfill된 값
  • 만약 Promisereject되면, await 문은 reject된 값을 throw

자바스크립트는 동기적이다. 즉, 순서대로 코드 블럭을 실행한다. 하지만 비동기 처리를 위해 callBack, Promise, async & await을 사용한다.

callBack


  • setTimeoutcallBack을 이용해 아래 코드를 비동기적으로 수행할 수 있다.
console.log(1); //sync
setTimeout(() => console.log(2), 1000); //async
console.log(3); //sync
 

// Synchronous callback
// 바로 hello가 콘솔에 출력된다.
function printImmediately(print) {
  print();
}
printImmediately(() => console.log('hello')); //sync


// Asynchronous callback
// 2초 뒤에 async callback가 출력된다.
function printWithDelay(print, timeout) {
  setTimeout(print, timeout);
}

printWithDelay(() => console.log('async callback'), 2000); //async
  • callBack을 이용하면 비동기 처리를 할 수 있지만 자칫 콜백 지옥에 빠질 수 있다.
setTimeout(
  (name) => {
    let coffeeList = name;
    console.log(coffeeList);

    setTimeout(
      (name) => {
        coffeeList += ', ' + name;
        console.log(coffeeList);

        setTimeout(
          (name) => {
            coffeeList += ', ' + name;
            console.log(coffeeList);

            setTimeout(
              (name) => {
                coffeeList += ', ' + name;
                console.log(coffeeList);
              },
              500,
              'Latte',
            );
          },
          500,
          'Mocha',
        );
      },
      500,
      'Americano',
    );
  },
  500,
  'Espresso',
);
  • 위 코드는 콜백 지옥 예시다. 가독성도 너무 어렵고 디버깅도 쉽지 않은 코드다. 콜백 지옥을 벗어나기 위해 Promise를 사용한다.

Promise


  • Promise 는 자바스크립트에 내장되어 있는 Object로 비동기적으로 수행할 때 유용하게 쓰인다.

  • PromiseProducerConsumer 개념이 있다.
    - ProducerPromise를 만드는 입장

    • ConsumerPromise를 소비하는 입장

Producer

  • 아래 코드는 Promise를 생성하는 코드다.
    새로운 Promise가 만들어질 때, executor 함수가 자동적으로 실행된다.
const promise = new Promise((resolve, reject) => {
	setTimeout(() => {
		resolve('kim');//기능을 잘 수행했을 경우 
      	reject(new Error('error'));
	}, 2000);
})

Consumer

promise.then(value => {
	console.log(value);//'kim'
}).catch(error => {
	console.log(error);//에러가 발생할 경우 'error'
}).finally(() => console.log('finally');//promise 수행 여부와 관계없이 finally는 수행된다.

Promise chaining

const fetchNumber = new Promise((resolve, reject) => {
  setTimeout(() => resolve(1), 1000);
});

fetchNumber
  .then(num => num * 2)
  .then(num => num * 3)
  .then(num => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(num - 1), 1000);
    });
  })
  .then(num => console.log(num));
  • 위 코드는 Promise chaining 나타내는데 코드가 길어질수록 이 또한 복잡하기 때문에 나온 대안이 async & await이다.

async & await


  • async & await을 사용하면 동기적으로 코드를 짜는 것처럼 비동기 처리를 할 수 있다.
  • function 앞에 async를 붙이면 코드 블럭안이 Promise로 자동 변환

async

async function fetchUser() {
	return 'ellie';
}

const user = fetchUser();
user.then(console.log); // ellie

await

  • await은 Promise타입 앞에만 쓸 수 있다.
  • await은 Promisefulfull상태가 되길 기다렸다가, 해당 fulfill된 값을 리턴한다.
function delay(ms) {
	return new Promise(resolve => setTimeout(resolve, ms));
}

async function getApple() {
  await delay(1000); //async가 붙은 함수안에서만 await을 쓸 수 있다.
  return '🍎'; //async가 있기 때문에 사과를 포함하는 promise를 반환
}

async function getBanana() {
  await delay(1000);
  return '🍌';
}

then


then은 무조건 Promise를 반환! 이 때 반환하는 Promise는 pending 상태의 Promise가 반환된다.

  • then에서 값을 그래도 리턴 하는경우에는 Promise.resolve(arg)을 리턴하는 것과 마찬가지다.
  • 프로미스를 반환받은 경우, 받은 프로미스는 다음 then에 노출된다.
// 그대로 값을 받은 경우
let promise = new Promise((resolve, reject) => resolve('성공'));

promise.then(val => {return val})
//위 코드의 경우 return val을 하는건 Promise.resolve(val)를 리턴하는 것과 같다.

// 프로미스를 반환받은 경우 
let promise = () => {
	return new Promise((resolve, reject) => {
	setTimeout(() => <resolve('성공'), 3000)
	})
}

promise().then(val => console.log(val)); //'성공'

await

profile
즐거운 코딩

0개의 댓글