[TIL#15]同期と非同期は何ですか?(Promise, async & await)


同期vs非同期


JavaScriptを学んだ後、初めて出会った重要な概念は同期と非同期です!
動機:上図のように、一つのことが終わってから次のことを実行する方法.
非同期:他のことの終わりにかかわらず、次のことを実行する方法を意味します.
JavaScriptには、指定されたイベントを処理するCall Stackが1つしかないため、同期方式を使用すると、複数のイベントは一度に1つのイベントしか実行できないため、長い時間待つ必要があります.そのため、JavaScriptは非同期方式に従います!

非同期の例

// 1번 Event
console.log("첫번째 이벤트");

//2번 Event
setTimeout(function() {
  console.log("두번째 이벤트");
}, 3000);

//3번 Event
console.log("세번째 이벤트");
同期言語を使用していますが、JavaScriptが初めて発生した場合は、上記のコードを実行します.
  • 第1イベント
  • (3秒後)2番目のイベント
  • 第3のイベント
  • この順番で出力すると思います.
    しかし、実際には、上記のコードを入力すると、次のような結果になります.
  • 第1イベント
  • 第3のイベント
  • (3秒後)2番目のイベント
  • この非同期方式に問題がある場合、そのうちの1つは1である.Backendサーバから任意のデータ2を要求します.Frontからデータを受信した後に非同期ストリームを処理せずにデータを使用するコードを実行する場合、サーバからデータを受信する前にデータを使用するのはでたらめです.

    非同期ストリーム処理方法


    1.コールバック地獄

    firstEvent(function(result1) {
      secondEvent(result1, function(result2) {
        thirdEvent(result2, function(finalresult) {
          console.log(finalresult);
        }, failureCallback);
      }, failureCallback);
    },failureCallback);
    関数A呼び出しでは、関数Bがパラメータとして渡される場合、関数Bをコールバック関数と呼ぶ.上記の例では、thirdEvent関数を呼び出すとsecondEventがパラメータとして渡され、secondEvent関数を呼び出すとfirstEventがパラメータとして渡され、これはまるで地獄に落ちたようだ.👿
    コードがより長く複雑になると、コードの可読性が低下し、後で修正が必要なことが発生すると、どこからどのように修正すればいいのか迷ってしまいます.このようなカルバック地獄問題を解決するためにPromiseが現れた.

    2. Promise



    Promiseでは、プロセッサを接続して、非同期操作が終了した後の結果値または失敗の原因を処理できます.すなわち,約束非同期演算が終了した後に取るべき行動である.
    Promiseには、次のいずれかの状態があります.
  • Pending(スタンバイ):初期状態未履行または拒否
  • Fulfilled(実行):演算成功完了
  • Rejected(拒否):演算失敗
  • Promiseの例


    1.Promiseの作成
    const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(200);
      },  1000);
    });
    new PromiseによってPromiseオブジェクトが生成され、パラメータとして関数が受け入れられ、この関数はresolve, reject関数がパラメータとして受け入れられる.
  • resolve:演算が正常に完了した最終結果を返す
  • reject:演算に失敗した場合は、Errorオブジェクトを返します.
  • 2.Promiseの使用
    promise
      .then(resolve => console.log(resolve);
            
    // 200이 출력된다.
    解析された値、すなわち正常に完了した結果値は、thenメソッドのパラメータに移動されます.
    const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject(404);
      },  1000);
    });
    
    promise
      .then(resolve => console.log(resolve);
      .catch(error => console.error(error);
    
    //error!가 출력된다.
    拒否された値、すなわち演算に失敗した場合、catchメソッドのパラメータに移動し、エラーハンドルを有効にします.
    3. Promise Chaining
    甑各タスクが前のステップの非同期操作に成功した後、その結果値を使用して次の非同期操作を実行する必要がある場合は、Chainingを使用して解決します.MDN
    doSomething()
     .then(result => doSomethingElse(result))
     .then(newResult => doThirdThing(newResult))
     .then(finalResult => {
       console.log(`Got the final result: ${finalResult}`);
     })
     .catch(failureCallback);
    上記のコードでは、doSomethingの戻り値がthen関数のパラメータとして渡され、doSomethingElse戻り値もdoThirdThing関数のパラメータとして渡されます.複数のPromiseオブジェクトのいずれかにエラーが発生した場合は、thenに移動します.
    4. Chaining after a catch
    Chainでは、タスクが失敗してcatchに移行した後も、新しいタスクを実行できます.
    new Promise((resolve, reject) => {
        console.log('시작');
        resolve();
    })
    .then(() => {
        throw new Error('에러 발생!');
        console.log('Do this');
    })
    .catch(() => {
        console.log('Do that');
    })
    .then(() => {
        console.log('catch 이후 then으로 넘어감');
    });
    上記のコードを実行すると、次のようになります.
    開始します.
    Do that
    catchの後thenに移動catch)でエラーが生成され、throw new Error('에러 발생!出力「Dothat」に直接ジャンプします.その後、次のcatchに移動します.

    3. async & await


    非同期関数宣言は、syncFunctionオブジェクトを返す非同期関数を定義します.非同期関数は、Promiseを使用して結果を暗黙的に返すイベントループを介して非同期で実行される関数です.MDN
    async&await(この2つは常にペアである)は、Promiseの代わりにPromiseを使用するのではなく、thenthenメソッドを使用して制御するのではなく、変数に戻り値を割り当てて記述できるようにします.

    async&待機例

    const resolveAfter2Seconds = () => {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve('resolved');
        }, 2000);
      });
    };
    
    const asyncCall = async () => {
      try{
        console.log('calling');
        const result = await resolveAfter2Seconds();
        console.log(result);
      }catch(error) {
        console.error(error);	// 에러 발생 시 catch 할 수 있도록 try/catch문으로 작성
      }
    };
    
    asyncCall();
    上記のように、Promiseとasync&awaitで記述されたコードを実行すると、次のようになります.
    calling
    resolved
    同期、非同期方式が最も機能する部分は、サーバ側とフロント間でデータを交換し、要求を送信するプロセスであるべきである.私も聴講の過程で同期、非同期処理の重要性を感じました.理論的にはまだまだ難しい内容ですが、プロジェクトを進めていくと、体で感じることでしょう.😅
    参考資料1
    参考資料2
    参考資料3