JavaScript非同期処理


初めてのモチベーション/非モチベーションの私の気持ち



同期/非同期

  • 同期と非同期を区別する基準は、実行順序の違いである.
    次の図に示すように、Synchronousはリクエストを送信し、リクエストの応答を受信します.
  • は、要求の応答に関係なく、非同期で次の操作を実行します.
  • どうきモード

  • 銀行番号を抽出!
    銀行の前の人の業務が終了してから私の番号になったときに私の業務が見えるように、一つのイベントがすべて終了するまで他のイベントを処理せず、前のイベントが完了した後に次のイベントを処理する実行順序が決定される=同期方式
  • 非同期

  • の食べ物を注文!
    レストランで順番に注文を受けても、まず人の食べ物を作って、次の人の食べ物を作ります.
    このように連続して発生するイベントはすべて受信、完了順に処理される実行順序が不確定=非同期方式
  • である.

    JavaScriptは単一Threadです。


    JavaScriptは単一のThread言語です.
    これは,イベントを処理するcall stack(関数が呼び出しスタックを実行する場所,呼び出し終了後に消える)が唯一の言語であることを意味する.
    したがって、複数のイベントを処理するときに同期処理を行うと、すべてのイベントを処理する前に他のイベントやタスクを実行できなくなります.
    「JavaScriptドライバ順序」を参照してください
    したがってjavascriptは、すぐに処理できないイベントをWeb APIに送信し、呼び出しスタックが空の場合、まず処理されたイベントをキューに入れ、その後、イベントキューに再キューに入れます.
    Web APIにアクセスする順序よりも、どのようなイベントを先に処理するかが重要です.
    非同期イベントの順序が重要になったらどうなりますか?
    サーバにログインするユーザーIDを要求して非同期処理を行った後、ユーザーIDを使用してプロファイル写真情報を再要求する必要がありますか?
    処理には順次行われる非動機的な種々の方法が必要である.

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


    1.CallBack関数の使用


    処理する必要があるイベントを順番にコールバック関数に入れる方法で、コールバック地獄と呼ばれます.
    doItFirst(function(result) {
      doItSecond(result, function(newResult) {
        doItThird(newResult, function(finalResult) {
          console.log('What is the last result : ' + finalResult);
        }, failureCallback);
      }, failureCallback);
    }, failureCallback);
    受信関数の初期戻り値resultは、次の非同期処理が必要な場合に受信関数をコールバックとして非同期処理する
    よく使われていますが、クラシックで致命的な欠点Oです.
  • 毒性が低下する。

  • 非同期処理が上記の例のように3つない場合、無限の地獄が見られる.
  • エラー処理を行う場合は、コールバックごとにエラーハンドルが必要です。

  • エラー処理もコールバックの深さとともに複雑になります.エラー処理を行わなくてもよいが,コールバック関数が呼び出されなければ,どこで発生し,なぜ発生したのかを知ることは困難である.
    このような不便を解消するために、Javascript ES 6のPromiseオブジェクトは非同期ストリーム制御方法を採用する.

    2.Promiseオブジェクト


    Promiseオブジェクトは、非同期操作が迎える将来の完了または失敗とその結果値を表します.
    ソースMDN
    Promiseを使用して、非同期操作の完了(成功または失敗)後の結果値を取得できます.
    結果値を返すことができるので、後続の処理を制御できます.
    Promiseのステータス値
    Promiseオブジェクトはnewキーワードで生成でき,4つの状態値がある.
    Pending: 아직 결과값이 반환되지 않은 진행중인 상태
    fulfilled: 성공
    Rejected: 실패
    Settled: 결과값이 성공 혹은 실패로 반환된 상태
    ステータス値は「完了」と「完了」に大別され、「完了」は「完了」と「完了」に大別されます.
    設定した値はやり直しできません.

    作成


    Promiseは関数をパラメータとして受け入れ,パラメータに入る関数はresolveとrejectedの2つの関数をパラメータとして再び受け入れる.
    resolveは非同期処理に成功したときに呼び出され、regecは非同期処理に失敗したときに呼び出される.
    const promise = new Promise(function(res, rej) {
      setTimeout(function() {
        res(111);
      }, 1000);
    });
    
    // 화살표 함수로 작성해도 동일
    const promise = new Promise((res, rej) => {
      setTimeout(()) => {
        res(111);
      }, 1000);
    });

    new Promiseを使用して作成したインスタンスオブジェクトは「オブジェクト」であるため、変数または関数として使用するパラメータとして指定できます。


    使用


    インスタンス呼び出しでは、thenおよびcatchの方法が一般的に使用される.
    resolve市then
    解析した値をメソッドのパラメータに移動します.
    const promise = new Promise((res, rej) => {
      setTimeout(() => {
        res(111);
      }, 1000);
    });
    
    promise.then((res) => console.log(res));
    
    // 출력값
    111
    廃品市catch
    resolveとは逆に,拒否された値をcatchメソッドのパラメータに渡してエラー処理を行うことができる.
    const promise = new Promise((res, rej) => {
      setTimeout(() => {
        rej('error!');
      }, 1000);
    });
    
    promise
      .then((res) => console.log(res))
      .catch((err) => console.log('error : ' + err));
    
    // catch 메소드에 잡혀서 console.log(err)에서 출력된 값
    error!
    ここで重要なのは、thenメソッドが再びPromiseに戻ることです.Promiseのオブジェクトを返すことは、thencatchの方法を使用することができ、thenの方法によって連続的なPromise chainingの方法を実現することができることを意味する.
    .catch()の後にリンクできます
    new Promise((res, rej) => {
      console.log('Initial');
      res(); // resolve된 후 then 실행
    })
    .then(() => {
      throw new Error('Something failed');
      console.log('Do this'); // error 발생으로 실행되지 않는다.
    })
    .catch((err) => {
      console.log(err); // throw new Error의 인자값이 넘어온다.
    })
    .then(() => {
      console.log('Do this, whatever happened before'); 
      // catch 구문 이후 chaining
    });
    
    // 출력값
    Initial
    Something failed // ERROR
    Do this, whatever happened before // catch 메소드 이후 then 메소드 실행  
    Promise.all
    Promise.all()メソッドは、巡回可能なオブジェクトに与えられたすべてのプロセス実行後、またはプロセスが提供されていない場合に実行されるPromiseを返します.
    指定されたプロセスが拒否された場合、最初に拒否されたプロセスの理由を使用して自分を拒否することもできます.
    ソースMDNPromise.allは、Promiseインスタンスを含む配列をパラメータとして使用し、配列内のすべての要素がPromiseインスタンスである必要はありません.
    const promise1 = Promise.resolve(3);
    const promise2 = 42; // 프로미스가 아니어도 괜찮아요~
    const promise3 = new Promise((resolve, reject) => {
      setTimeout(resolve, 100, 'foo');
    });
    
    Promise.all([promise1, promise2, promise3]).then(values => {
      console.log(values); // Array [3, 42, 'foo']
    });
    
    // resolve되는 값들을 destructuring 할 수 있다.
    Promise.all([promise1, promise2, promise3])
    .then(([one, two, three]) => {
      console.log(one); // 3
      console.log(two); // 42
      console.log(three); // 'foo'
    });
    Promise非インスタンス使用例
    const emptyPromiseAll = Promise.all([]); // 빈 배열을 동기적 실행
    
    // 프로미스가 아닌 값은 무시하지만 비동기적으로 실행됨
    const promiseA = Promise.all([1337, "hi"]); 
    // 위와 동일
    const promiseB = Promise.all([1, 2, 3, Promise.resolve(444)]);
    
    
    p; // [] 동기적 실행히라 then 메소드 사용하지 않아도 된다. 
    p2.then(res => console.log(res)); // [1337, 'hi']
    p3.then(res => console.log(res)); // [1, 2, 3, 444]
    MDNには多くの異なる例があり、同期、非同期実行の違い、および非同期実行時に保留された場合を開発者ツールウィンドウに直接印刷することが望ましい.

    3. async / await


    async関数宣言は非同期関数を定義し、asyncFunctionオブジェクトを返します.
    非同期関数は、Promiseを使用して結果を暗黙的に返すイベントループを介して非同期で実行される関数です.
    非同期関数を使用するコードの構文と構造は、標準同期関数を使用するのとよく似ています.
    ソースMDN
    ES 2017のasync / await構文は、上記MDNに記載されているように、Promiseに基づいて使用され、非同期コードが同期コードのように記述されることを可能にする.
    今回のプロジェクトでは.then, .catch構文しか使いませんが、async/awaitを使ってみる必要があります.
    覚えておいてください.async / awaitPromiseに取って代わったわけではありません.Promiseを使用しますが、thenメソッドとcatchメソッドを使用すると、同期コードではなく変数に戻り値を割り当てることができます.
    awaitキーワードはasync関数でのみ使用できますが、async以外の関数で使用すると、次のようにSyntaxErrorが発生します.

    error handlingtry.. catch..構文を使用すると、Promise chainingに接続されたthenメソッドのいずれかが、エラー発生時にcatchメソッドをキャプチャするように、非同期処理中にエラーが発生した場合にcatch blockでキャプチャされる.
    function promise() {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve('resolved');
        }, 2000);
      });
    }
    
    async function asyncCall() {
      try {
          console.log(1);
          const result = await promise(); // Promise가 settled될 때까지 기다린 후 resolve된 값을 할당한다.
          console.log(result);
          console.log(2);
      } catch(err) {
        console.error(err); // error 발생 시 catch 블락에서 잡히도록 handling
      }
    }
    
    asyncCall();
    
    // 출력 값
    1  // asyncCall 호출
    resolved  // resolve 함수 호출
    2  // await 후 다음 코드 실행
    次の状況は?
    console.log(0);
    
    function promise() {
      console.log(1);
      
      return new Promise(resolve => {
        setTimeout(() => {
          
          console.log(2);
          resolve('resolved');
        }, 2000);
      });
    }
    
    console.log(3);
    
    async function asyncCall() {
      try {
          console.log(4);
        
          const result = await promise(); // Promise가 settled될 때까지 기다린 후 resolve된 값을 할당한다.
        
          console.log(result); 
          console.log(5);
      } catch(err) {
        console.error(err); // error 발생 시 catch 블락에서 잡히도록 handling
      }
    }
    
    console.log(6);
    
    asyncCall();
    
    // 출력 값
    0
    3
    6
    4  // asyncCall 호출
    1  // promise 함수 호출
    2  // 2초 후 setTimeout 콜백 함수 호출
    resolved // resolve함수 호출
    5  // await 후 다음 코드 실행
    2つの例では、awaitを呼び出す関数出力値resultが割り当てられたコンソールに注意が必要である.これらのログ.
    非同期の場合、どのイベントが最初に完了するかは不明です.async awaitを使用する場合、必要に応じて先に完了するイベントの順序で、同期して実行されるコードに記述することができる.

    What I truly say...

  • コールバック関数
  • を使用
  • Promise - then, catch
  • Promiseを使用したasync/await
  • 実際のコードを記述する場合、axiosまたはfetchを介してサーバに要求を発行すると、Promiseが自動的に返されるため、Promiseオブジェクトを直接生成するよりもPromise非同期処理を用いてasync awaitのオブジェクトを返すことが多い.
    ただし、使用時にプロセスを理解するには、Promiseの駆動方法を理解する必要があります.Finally async/awaitを使用してみます