[深い]プロミス



保証する


JavaScriptはコールバック関数を非同期処理の1つのモードとして使用する
=>ダイヤルバックhellの読み取りが悪く、非同期処理中に発生したエラーは処理しにくく、1回に複数の非同期処理を処理するのも限られている
ES 6は、非同期処理の別のモードとして프로미스を採用する.

非同期コールバックモードの欠点

비동기 함수は、関数の内部で非同期に実行されるコードを含む関数です.非同期関数の非同期コードは、非同期関数が終了した後に完了します.
=>非同期関数の内部で非同期で実行されているコードで処理結果を外部に戻すか、親ミラー変数に処理結果を割り当てると、予想通りに実行されません.
=>非同期関数は、非同期処理結果を外部に戻すことはできません.親ミラーの変数に割り当てることもできません.
したがって,非同期関数の処理結果を非同期関数内部で後続処理する必要がある.通常、非同期関数にコールバック関数を提供し、非同期処理が成功した場合にコールバック関数を呼び出し、非同期処理が失敗した場合にコールバック関数を呼び出すために、非同期処理結果の後続処理を実行します.
しかし,この方式はコールバック関数呼び出しが重なるため,より複雑度の高いコールバックhellに陥る確率が高く,エラー処理にも一定の限界がある.

プロセスの作成


このため、ES 6はPromiseを導入した.PromiseはECMAScript仕様で定義された標準構築オブジェクトであり、Promise構造関数は、resolveおよびrejectをパラメータとして受信する非同期処理を実行するコールバック関数をパラメータとして受信する.
  • 非同期処理に成功すると、コールバック関数のパラメータによって伝達されるresolve関数呼び出し
  • が行われる.
  • の非同期処理が失敗した場合、reject関数が呼び出される.
  • 「状態」(State)情報は、現在の非同期処理の進行状況を示し、以下のようになる.
  • pending:非同期処理はまだ実行されていません.プロセスの作成後のデフォルトの状態.
  • 完了
  • :非同期処理が実行されました(成功).呼び出しresolve関数
  • 却下:非同期処理の実行(失敗).呼び出し拒否関数
  • このプロセスのステータスは、解析関数または拒否関数の呼び出しによって決まります.fulfilledまたはrejected状態をsettled状態と呼ぶ.settled状態はpending状態ではなく、非同期処理状態である.settledの状態になると、他の状態に変更することはできません.
    プロセスは非同期処理状態と同時に非同期処理結果を有する.
    すなわち,プロセスは非同期処理状態と処理結果を管理するオブジェクトである.

    Premis後続処理方法


    プロセスの非同期処理状態が変化する場合、対応する後続処理が必要であり、このプロセスに後続の方法then, catch, finallyが提供される.
    プロセスとの非同期処理状態が変化すると、パラメータとして後続の処理方法に渡される콜백 함수が選択的に削除され、このときプロセスの처리 결과がパラメータとして後続の処理方法のコールバック関数に渡される.

    Promise.prototype.then


    次に、メソッドは2つのコールバック関数をパラメータとして渡します.
  • 最初のコールバック関数は、プロセスが完了すると呼び出されます.コールバック関数は、プロセスの非同期処理結果を引数として渡します.
  • 第2のコールバック関数は、プロセスが拒否されたときに呼び出される.コールバック関数は、プロセスエラーをパラメータとして渡します.
  • Promise.prototype.catch


    catchメソッドは、コールバック関数を引数として渡します.catchメソッドのコールバック関数は、プロセスがrejectedの状態にある場合にのみ呼び出されます.

    Promise.prototype.finally


    finallyメソッドは、パラメータとしてコールバック関数を受信します.プロセスが成功しても失敗しても、一度呼び出すだけで、プロセスの状態にかかわらず、共同で実行する必要がある処理があります.
    以上の3つの方法は常にpromisを返します.コールバック関数がプロセス以外の値を返す場合は、値を暗黙的に解析または拒否することでプロセスを作成して返します.

    エラー処理

    const wrongUrl = 'https://jsonplaceholder...';
    
    promiseGet(wrongUrl)
      .then(res => console.log(res));
      .catch(err => console.error(err));
    then法を用いて第2のコールバック関数を伝達するよりも、catch法を用いた方が可読性と明確性が高い.したがって,thenメソッドではエラー処理を行わず,catchメソッドで行うことを提案する.

    創造する

    const url = 'https://...';
    
    promiseGet(`${url}/posts/1`)
      .then(({ userId }) => promiseGet(`${url}/users/${userId}`))
      .then(userInfo => console.log(userInfo))
      .catch(err => console.error(err));
    上記の例では、後続の処理方法がthe->then->catchの順序で呼び出され、then, catch, finallyの後続の処理方法は常にプロセスに戻るので、連続的に呼び出すことができる.프로미스 체이닝と呼ばれています.
    プロセスは프로미스 체이닝によって非同期処理結果を受信し、後続の処理を行うため、非同期処理のコールバックモードでコールバックhellは発生しない.
    しかし、プロミスは最終的にダイヤルバックモードを使用し、ダイヤルバックモードの可読性が悪い.
    =>ES 8導入のasync/awaitソリューション

    マイクロタスクキュー

    setTimeout(() => console.log(1),0);
    
    Promise.resolve()
      .then(() => console.log(2))
      .then(() => console.log(3));
    2->3->1の順で出力します.これは、Promisの後続の処理方法のコールバック関数が태스크 큐ではなく마이크로태스크 큐に格納されるためである.마이크로태스크 큐は、태스크 큐とは独立したキューであり、Promisの後続処理方法のコールバック関数を一時的に記憶する.마이크로태스크 큐の優先度は태스크 큐より高い.すなわち、callスタックが空の場合、イベントループは、마이크로태스크 큐に待機している関数を最初にインポートして実行し、마이크로태스크 큐に待機している関数をインポートして実行する.

    fetch

    태스크 큐オブジェクトと同様に、HTTP要求伝送機能を有するクライアントサイトWeb APIXMLHttpRequest関数は、HTTPリクエストを送信するURLと、HTTPリクエストメソッド、HTTPリクエストヘッダ、ペイロード等が設定されたオブジェクトを渡す.
    const promise = fetch(url,[, options])
    fetch('https://...);
      .then(response => console.log(response));
    fetch関数が返すプロセスはfetchオブジェクトを404 Not Foundに設定し、HTTPエラー(500 Internal Server Errorrejectなど)が発生した場合、エラーをResponseに設定せず、ブールタイプのokステータスをfalseに設定します.resolveプロトコルは、ネットワーク障害(例えばオフライン)またはCORSエラー要求が完了していない場合にのみ実行されます.
    したがって、reject関数を使用する場合、fetch関数が返すpromisがfetchであるかどうかを確認して、エラーを明確に処理する必要がある.
    const wrongUrl = 'https://...';
    
    fetch(wrongUrl)
      .then(response => {
        if(!response.ok) throw new Error(response.statusText);
        return response.json();
      })
      .then(todo => console.log(todo))
      .catch(err => console.error(err));