Promise

»

Promise

Promise 개체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다

  • 매개변수 우선 Promise 는 매개변수로 executor 를 받게 됩니다 executorresolvereject 인수를 전달할 실행함수입니다 비동기 작업이 모두 끝나면 resolve 를 호출해 이행하고 중간에 오류가 생기면 reject 를 이용해 거부하게 됩니다
  • 상태
    • pedding : 대기 상태로서 아직 resolve 할지 reject 할 지 결정되지 않은 초기의 상태
    • fullfilled : 이행 상태로서 연산이 성공적으로 완료된 상태입니다
    • rejected : 거부 상태로서 연산이 실패한 상태입니다

콜백 지옥을 벗어나기 위한 함수

  • then promise 가 종료가 되면 resolve 에 들어간 값을 받을 수 있습니다

    ```jsx
    const promise = new Promise((resolve, reject)=>{
      setTimeout(()=>{
        resolve("resolve");
      }, 3000);
    });
    
    promise.then(value => console.log(value));
    // 3초 후에 결과가 출력
    // resolve
    ```
    
  • catch 그러나 reject 된 경우에 then 을 ㅗ받을 경우 에러가 발생하게 됩니다, 이때 catch를 사용해서 에러를 잡아주게 됩니다

    ```jsx
    const promise = new Promise((resolve, reject)=>{
      setTimeout(()=>{
        reject("reject");
      }, 3000);
    });
    
    promise.then(result => console.log(result)).catch(error => console.log(error));
    // 3초 후에 결과가 출력
    // reject
    ```
    
  • Promise callback

    // Callback -> Promise
    const printString = string => {
      return new Promise((resolve, reject) => {
        setTimeout(
          () => {
            console.log(string);
            resolve();
          },
          Math.floor(Math.random() * 100) + 1;
        )
      })
    }
    
    const printAll = () => {
      printString('A')
      .then(() => {
        return printString('B');
      })
      .then(() => {
        return printString('C');
      })
    }
    printAll();
    
  • Promise chaining

    상황에 따라 promise 를 여러번 사용해야 하는 경우가 존재한데 이때 마치 chain이 연결된 것처럼 then 을 원하는 만큼 많이 연결할 수 있습니다

    근데 만약에 에러가 발생한다? 그러면 그냥 catch 한 번으로 모든 then에 해당하는 에러를 잡을 수가 있습니다

    const promise = new Promise((resolve, reject) => {
      resolve(2);
    });
    
    const plusOne = (num) => num + 1;
    
    promise
      .then(plusOne)
      .then(plusOne)
      .then(plusOne)
      .then(() => {
        throw Error("error");
      })
      .then((result) => console.log(result))
      .catch((error) => console.log(error));
    // Error: error
    
  • Promise all

    all() 은 주어진 모든 Promise를 실행한 후 진행되는 하나의 Promise를 반환합니다

    여러개의 promise에 대해 이들을 arrayall에 넘겨주게되면 allPromise 는 3개의 promise가 모두 끝날때까지 기다린 후에 이들의 결과값을 array로 반환

    const p1 = new Promise((resolve, reject) => {
      setTimeout(reject, 2000, "First reject");
    });
    
    const p2 = new Promise((resolve) => {
      setTimeout(resolve, 1000, "Second");
    });
    
    const p3 = new Promise((resolve) => {
      setTimeout(resolve, 3000, "Third");
    });
    
    const allPromise = Promise.all([p1, p2, p3]);
    allPromise
      .then((values) => console.log(values)) // [ 'First', 'Second', 'Third' ]
      .catch((error) => console.log(error));
    // First reject
    
  • Promise race

    race() 는 주어진 promise 중 가장 먼저 완료된 것의 결과값을 이행하거나 거부합니다

    all 과 비슷합니다

    p1reject 하고 있지만 결과는 Second가 나옵니다

    p2 는 1초만에 끝나기 때문에 그 결과값을 받아 바로 출력해버리는 겁니다

    const p1 = new Promise((resolve, reject) => {
      setTimeout(reject, 2000, "First reject");
    });
    
    const p2 = new Promise((resolve) => {
      setTimeout(resolve, 1000, "Second");
    });
    
    const p3 = new Promise((resolve) => {
      setTimeout(resolve, 3000, "Third");
    });
    
    const allPromise = Promise.race([p1, p2, p3]);
    allPromise
      .then((values) => console.log(values))
      .catch((error) => console.log(error));
    // Second
    
  • Promise finally

    finally()Promiseresolve 되던 reject 되던 상관없이 지정된 함수를 실행합니다

    이를 통해 promise 의 결과에 상관없이 동작을 해야할 때 유용하게 구현할 수 있습니다

    해당 예시가 중간에 에러가 발생하고 이를 catch로 잡아 주었어도 fianlly는 실행되어 end를 출력합니다

    const p1 = new Promise((resolve, reject) => {
      setTimeout(resolve, 2000, "First");
    });
    
    p1.then((result) => console.log(result)).finally(() => console.log("end"));
    // First
    // end
    
  • async await

    사용방법은 다음과 같습니다

    // 일반함수
    async function myFunc() {}
    
    // 화살표 함수
    myFunc = async () => {};
    

    await 는 항상 async로 정의된 함수 내에서만 사용이 가능합니다

    then 과 비슷한 역할로써 promise가 끝나기를 기다립니다

    movieListAsync = async () => {
      const response = await fetch("https://yts.lt/api/v2/list_movies.json");
      console.log(response);
      const json = await response.json();
      console.log(json);
    };
    
  • Try Catch

    async 방식으로 catch를 대체할 수 있습니다

    실행할 코드를 try로 감싸주고 그 뒤에 catch 는 에러메시지를 인자로 받습니다

    try 내부라면 어디서 에러가 일어나도 catch 가 이를 전부처리합니다

    movieListAsync = async () => {
      try {
        const response = await fetch("https://yts.lt/api/v2/list_movies.json");
        const json = await response.json();
        console.log(json);
      } catch (e) {
        console.log(e);
      }
    };
    
  • finally

    finally 또한 Try Catch와 비슷합니다

    movieListAsync = async () => {
      try {
        const response = await fetch("https://yts.lt/api/v2/list_movies.json");
        const json = await response.json();
        console.log(json);
      } catch (e) {
        console.log(e);
      } finally {
        console.log("finally");
      }
    };
    
  • Parallel

    all 을 통해 fetch 두 개를 받고 다시 all 을 한번 더 사용하여 json 형식으로 바꿔줍니다

    movieListAsync = async () => {
      try {
        const [moviesResponse, suggestionsResponse] = await Promise.all([
          fetch("https://yts.lt/api/v2/list_movies.json"),
          fetch("https://yts.lt/api/v2/movie_suggestions.json?movie_id=100"),
        ]);
    
        const [movies, suggestions] = await Promise.all([
          moviesResponse.json(),
          suggestionsResponse.json(),
        ]);
    
        console.log(movies, suggestions);
      } catch (e) {
        console.log(e);
      } finally {
        console.log("finally");
      }
    };