JavaScript の then() 関数はどういう意味ですか? 質問する

JavaScript の then() 関数はどういう意味ですか? 質問する

次のようなコードを見かけました:

myObj.doSome("task").then(function(env) {
    // logic
});

どこthen()から来たのですか?

ベストアンサー1

JavaScript で非同期呼び出しを処理する従来の方法は、コールバックを使用することです。アプリケーションをセットアップするために、サーバーに 3 回連続して呼び出しを行う必要があるとします。コールバックを使用すると、コードは次のようになります (サーバー呼び出しを行う xhrGET 関数を想定)。

// Fetch some server configuration
    xhrGET('/api/server-config', function(config) {
        // Fetch the user information, if he's logged in
        xhrGET('/api/' + config.USER_END_POINT, function(user) {
            // Fetch the items for the user
            xhrGET('/api/' + user.id + '/items', function(items) {
                // Actually display the items here
            });
        });
    });

この例では、まずサーバー構成を取得します。次に、それに基づいて現在のユーザーに関する情報を取得し、最後に現在のユーザーのアイテムのリストを取得します。各 xhrGET 呼び出しは、サーバーが応答したときに実行されるコールバック関数を受け取ります。

もちろん、ネストのレベルが高ければ高いほど、コードの読み取り、デバッグ、保守、アップグレード、および基本的に操作が難しくなります。これは一般にコールバック地獄として知られています。また、エラーを処理する必要がある場合は、エラーが発生した場合に何を行う必要があるかを指示するために、各 xhrGET 呼び出しに別の関数を渡す必要がある可能性があります。共通のエラー ハンドラーを 1 つだけ用意したい場合は、それは不可能です。

Promise API は、このネストの問題とエラー処理の問題を解決するために設計されました。

Promise API は以下を提案します。

  1. 各非同期タスクはpromiseオブジェクトを返します。
  2. 各オブジェクトには、ハンドラーとハンドラーの2 つの引数を取ることができる関数promiseがあります。thensuccesserror
  3. 関数内の成功またはエラー ハンドラは、非同期タスクが終了した後に1 回thenだけ呼び出されます。
  4. この関数は、複数の呼び出しを連鎖できるようにthenも返します。promise
  5. 各ハンドラ (成功またはエラー) は を返すことができ、これはのチェーン内のvalue次の関数に として渡されます。argumentpromise
  6. ハンドラーが を返す場合promise(別の非同期要求を行う)、次のハンドラー (成功またはエラー) はその要求が完了した後にのみ呼び出されます。

$httpしたがって、前のサンプル コードは、Promise とサービス (AngularJs 内)を使用して、次のように変換できます。

$http.get('/api/server-config').then(
    function(configResponse) {
        return $http.get('/api/' + configResponse.data.USER_END_POINT);
    }
).then(
    function(userResponse) {
        return $http.get('/api/' + userResponse.data.id + '/items');
    }
).then(
    function(itemResponse) {
        // Display items here
    }, 
    function(error) {
        // Common error handling
    }
);

成功とエラーの伝播

プロミスのチェーン化は非常に強力なテクニックであり、サービスにサーバー呼び出しを行わせ、データの後処理を行ってから、処理済みのデータをコントローラーに返すなど、多くの機能を実現できます。ただし、promiseチェーンを使用する場合は、いくつか留意すべき点があります。

promiseP1、P2、P3 という 3 つのプロミスを含む次の仮想チェーンについて考えてみましょう。それぞれにpromise成功ハンドラーとエラー ハンドラーがあるため、P1 には S1 と E1、P2 には S2 と E2、P3 には S3 と E3 があります。

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3

エラーのない通常のフローでは、アプリケーションは S1、S2、そして最後に S3 の順に流れます。しかし、現実には物事はそれほどスムーズには進みません。P1 でエラーが発生したり、P2 でエラーが発生して E1 または E2 がトリガーされたりすることがあります。

次のケースを考えてみましょう。

• P1 でサーバーから正常な応答を受け取りましたが、返されたデータが正しくないか、サーバー上に利用可能なデータがありません (空の配列を考えてください)。このような場合、次のプロミス P2 では、エラー ハンドラー E2 をトリガーする必要があります。

• プロミス P2 のエラーが発生し、E2 がトリガーされます。ただし、ハンドラー内にはキャッシュからのデータがあり、アプリケーションを通常どおりロードできることが保証されています。その場合、E2 の後に S3 が呼び出されるようにする必要があります。

したがって、成功ハンドラーまたはエラーハンドラーを記述するたびに、現在の関数を前提として、このプロミスはプロミス チェーンの次のハンドラーにとって成功か失敗かを呼び出す必要があります。

チェーン内の次のプロミスの成功ハンドラをトリガーしたい場合は、成功ハンドラまたはエラーハンドラから値を返すだけです。

一方、チェーン内の次のプロミスのエラーハンドラをトリガーしたい場合は、deferredオブジェクトを使用してそのreject()メソッドを呼び出すことができます。

さて、遅延オブジェクトとは何でしょうか?

jQuery の遅延オブジェクトは、通常は非同期で後で完了する作業単位を表します。作業単位が完了すると、オブジェクトはdeferred解決済みまたは失敗に設定できます。

オブジェクトにはオブジェクトdeferredが含まれていますpromisepromiseオブジェクトを介して、作業単位が完了したときに何が起こるかを指定できます。これを行うには、promiseオブジェクトにコールバック関数を設定します。

JQuery の遅延オブジェクト:https://api.jquery.com/jquery.deferred/

AngularJs の遅延オブジェクト:https://docs.angularjs.org/api/ng/service/$q

おすすめ記事