TIL 22 | Promise


https://youtu.be/JB_yU6Oe2eE
『DREAMCODINGBY ELLY』のYouTube講座を見て整理した内容です

1.Promiseコンセプト


Promiseは、JavaScriptが提供する非動機的なオブジェクトを簡単に処理できるオブジェクトです.
既定の機能を長時間実行した後、
  • 機能が正常である場合→成功したメッセージと処理の結果値
  • を渡す.
  • 機能の実行中に予期せぬ問題が発生した場合→エラーが発生します.
  • これはコールバック関数に代わる有用なオブジェクトです.🙂

    1-1. state


    state : pending → fulfilled or rejected
  • promiseのstateはpromiseを作成し、指定した操作が実行中である場合、
  • に保留されます.
  • 操作が正常に完了すると、完了状態になります.
  • ではなく、ファイルまたはネットワークに問題が発生しない場合は、拒否されます.
  • 1-2. producer vs consumer


    Producer vs Consumer
  • とPromiseは、対応するデータを作成するために必要な機能を提供します.
    (=projectobject)
  • は、提供されたデータを需要または消費のConsumerに分割する.
  • 2. Producer


    when new Promise is created, the executor runs automatically !
    目的の機能を非同期で実行する約束を作成しましょう.promiseはクラスであるため、newというキーワードを使用してobjectを生成することができます.
    さらにpromiseはexecutorというコールバック関数を渡す必要があり、このコールバック関数は2つのコールバック関数(resolve、rejcet)を受け入れる.
    const promise = new Promise((resolve, reject) => {
      // doing some heavy work (network, read files)
      console.log('doing something...');  // doing something... 이 바로 출력된다.
    });
    →約束の中で重いことをするのが普通です.ネットワークからデータを受信したり、ファイルから大きなデータを読み取るのに時間がかかるからです.これらの処理を同期(=非同期)にすると、ファイルを読み取り、ネットワークからデータを受信する過程で、次の行のコードは実行されません.そのため、promiseとして作成し、非同期処理するのに時間がかかることがあります.
    🤚🏻 約束の瞬間をつくる!私たちが渡したexecuterというコールバック関数は実行されます.すなわち、promiseでネットワーク通信を行うコードを記述すれば、promiseが作成された瞬間にネットワーク通信を実行することができる.
    したがって、ネットワーク要求は、ユーザが必要とする場合にのみ発行される.上記のように記述すると、ユーザが要求しない場合、不要なネットワーク通信が発生するため、作成が承諾されると、executerというコールバック関数が直ちに実行されることに注意してください.

    2-1. 生産者の作成


    あることを2秒ほどして、最後に仕事をして、resolveのコールバック関数を呼び出して、「eden」値のpromiseを作成します.
    const promise = new Promise((resolve, reject) => {
      //doing some heavy work
      console.log("doing something...");
      setTimeout(() => {
        resolve("eden");  // 성공적으로 잘 마쳤어! .... resolve 콜백함수 호출
      }, 2000);
    });
    機能が正常に実行されると、→resolve()というコールバック関数が呼び出され、そのresolve()コールバック関数を介して正常に受信したデータが渡されます.
    👏🏻 Promiseという名前のProducerを作成した以上、それを使用するConsumerを作成しましょう.

    3. Consumers


    消費者は、thenまたはcatchおよび最近増加したfinallyを使用して値上げすることができる.

    3-1. then

    2-1で作成された承諾という変数を使用すると、値は正常に実行されます.
    → .次にvalueを取得し、必要な機能を実行するコールバック関数に渡します.
    // 2-1에서 만든 promise
    const promise = new Promise((resolve, reject) => {
      //doing some heavy work
      console.log("doing something...");
      setTimeout(() => {
        resolve("eden");  // 성공적으로 잘 마쳤어! .... resolve 콜백함수 호출
      }, 2000);
    });
    promise.then((value) => {  //value가 전달된다.
      console.log(value);      // ...2초 뒤 "eden" 출력된다.
      //이렇게 value가 전달되면 이것을 콘솔로그에 출력해준다. 
    });
    value:valueというパラメータはpromiseが正常に実行された結果であり,最後に解析コールバック関数が伝達する値「eden」が得られた.
    すなわちthenとはpromiseが正常に実行され,最終的にdiscoverというコールバック関数によって伝達される値がvalueパラメータとして伝達されることを指す.

    3-2. catch


    ネットワークで何か失敗があったら、resolveではなくexecuteを呼び出してみましょう.
    まだあります.catchという名前の関数を使用してコールバック関数を登録し、エラーが発生したときにどのように処理するかを指定します.
    一般にerror(new error)というobjectによって値が伝達される.
    //producer
    const promise = new Promise((resolve, reject) => {
      //doing some heavy work (network, readfiles)
      console.log("doing something...");
      setTimeout(() => {
        //resolve("eden");
        reject(new Error("no network"));  //어떤 에러가 발생했는지 이유를 잘 써주기!
      }, 2000);
    });
    
    //consumer
    promise
      .then((value) => {  //성공한 거 받기
        console.log(value);
      })
      .catch((error) => {  //실패(error) 받기
        console.log(error);
      });
    Error:ErrorクラスはJavaScriptが提供するオブジェクトの1つです.あるエラーが発生したことを示し、通常error objectにどのエラーが発生した原因を明記すべきかを示す.
    💡 chaining .thenが呼び出されると、最終的には同じ承諾が再び返され、返された承諾に.catchが登録される.これはチェーンと呼ばれています.(arrayで.map()です.sort().join() ... このようにロックされているようです!)

    3-3. finally


    最近追加されました.finallyは成功しても失敗しても、最後に呼び出されます.成功と失敗にかかわらず、最後に機能を実行したい場合はfinallyを使用します.
    promise(
      .then((value) => {
        console.log(value);
      })
      .catch((error) => {
        console.log(error);
      })
      .finally(() => {  //아무런 인자를 받지 않고 콘솔로그를 출력,,
        console.log("finally");
        // 실패했을 때도 error 콜백함수가 처리되고 나서 "finally"가 호출되고,
        // 성공했을 때도 그에 따른 콜백함수가 수행된 후 "finally"가 호출된다.
      });
    );

    4. 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));  //2초뒤 ... 5 출력
    →そうですか.then .then .then .その後、複数を同時にパッケージ化したり、他の非同期のものをパッケージ化したりすることができます.

    5. Error handling


    次はpromiseを返す3つの関数です.
    //암탉을 받아오는 promise는 1초 있다가 닭을 return한다.
    const getHen = () => 
      new Promise ((resolve, reject) => {	
        setTimeout(() => resolve("🐓"), 1000);
      });
    
    //get Egg는 닭을 받아서 그 닭으로부터 => 달걀을 얻어오는 promise를 return한다. 
    const getEgg = (hen) => 
      new Promise ((resolve, reject) => {   
        setTimeout(() => resolve(`${hen} => 🥚`), 1000);
      });
    
    // cook은 달걀을 받아와서 달걀을 가지고 fried egg를 만드는 함수이다.
    const cook = (egg) => 
      new Promise ((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => 🍳`), 1000);
      });
    getHen()
      .then((hen) => getEgg(hen))
      .then((egg) => cook(egg))
      .then((meal) => console.log(meal));  //🐓 => 🥚 => 🍳
    🤚🏻 コールバック関数を渡すときに別の関数を直接呼び出す場合は、この関数を省略できます.✂️
    getHen()  // 프리티어 포멧에서 한 줄로 바꿔버리기 때문에 이렇게 주석 표시해주면 엔터 처리 가능하다!
      .then(getEgg)
      .then(cook)
      .then(console.log);  //🐓 => 🥚 => 🍳

    5-1. error handling: catch

    const getHen = () => 
      new Promise ((resolve, reject) => {	
        setTimeout(() => resolve("🐓"), 1000);
      });
    const getEgg = (hen) => 
      new Promise ((resolve, reject) => {   
        setTimeout(() => reject(new Error(`error! ${hen} => 🥚`)), 1000); //여기서 발생하는 에러를 처리해보자!
      });
    const cook = (egg) => 
      new Promise ((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => 🍳`), 1000);
      });
    
    getHen()  //
      .then(getEgg)
      .then(cook)
      .then(console.log); //catch를 처리해주지 않으면 여기서 에러가 발생한다.
    次に、エラー制御を行うためにcatchを追加します.
    getHen()  //
      .then(getEgg)
      .then(cook)
      .then(console.log)
      .catch(console.log);  //Error: error! 🐓 => 🥚
    →卵を受け取った部分(getEGG)でエラーが発生しましたが、エラーが下記に伝わりcatchにキャプチャされてコンソールウィンドウにエラーメッセージが出力されます.

    5-2. 置換エラー

    getHen()
      .then((hen) => getEgg(hen))
      .catch((error) => {  //여기서 계란을 받아올 때 문제가 생긴다면,
        return "🍞";       //우리가 다른 것을 전달해 줄 거다.
      })
      .then((egg) => cook(egg))
      .then((meal) => console.log(meal))
      .catch(console.log);  // 🍞 => 🍳
    →卵(GetEGG)の受け取りに失敗しましたが、パンを送ってくれたのでこのpromise chainは失敗せず、最終的に最後の料理を完成しました.
    💡 そこで発生したエラーを処理したい場合→すぐにcatchと書いて、すぐに問題を解決します.

    6.callback地獄コードの改善


    しかし、これも改善できます.😇