web-dev-qa-db-ja.com

コールバックが約束よりも「密結合」なのはなぜですか?

次のフレーズを説明してもらえますか( Stack Overflowの質問への回答 JavascriptのDeferred、Promise、Futureの違いは何ですか? )。

jQuery を使用することの利点は、以前のjQueryコールバックの使用に対して何ですか?

Promiseを使用すると、コールバックを関数に直接渡すのではなく、密結合されたインターフェイスにつながる可能性があるため、同期または非同期のコードに対する懸念を分離できます。

35
Revious

約束はコールバックよりも多かれ少なかれ、ほぼ同じだとは思いません。

ただし、約束には他の利点もあります。

  • コールバックを公開する場合、jQuery.ajaxのように1回呼び出されるか、Array.mapのように複数回呼び出されるかを文書化する必要があります。約束は常に1回呼び出されます。

  • コールバックをスローして例外を呼び出す方法はないため、エラーの場合には別のコールバックを提供する必要があります。

  • 約束のために複数のコールバックを登録することができ、イベントの後でそれらを登録することができ、とにかく呼び出されます。

  • 型付き宣言(TypeScript)では、Promiseは署名を読みやすくします。

  • 将来的には、非同期/ yield構文を利用できます。

  • これらは標準であるため、次のような再利用可能なコンポーネントを作成できます。

     disableScreen<T>(promiseGenerator: () => Promise<T>) : Promise<T>
     {
         //create transparent div
         return promiseGenerator.then(val=>
         {
            //remove transparent div
            return val;
         }, error=>{
             //remove transparent div
             throw error;
         });
     }
    
     disableScreen(()=>$.ajax(....));
    

詳細: http://www.html5rocks.com/en/tutorials/es6/promises/

編集:

  • 別の利点は、NレベルのインデントなしでN非同期呼び出しのシーケンスを記述することです。

また、私はまだそれが主なポイントだとは思いませんが、今では、これらの理由から、それらはもう少し疎結合になっていると思います:

  • それらは標準です(少なくとも試してみてください):C#のコードまたはJava文字列を使用するJava $ ===は、C++の同様のコードよりもひどい結合です。標準の約束を持っているので、呼び出し元と実装は、カスタムパラメータの順序、名前などのカスタムコールバック(のペア)に同意する必要がないため、相互の結合度が低くなります。約束のフレーバーは考えを助けません。

  • これらは、より表現ベースのプログラミングを促進し、作成、キャッシュなどを容易にします。

      var cache: { [key: string] : Promise<any> };
    
      function getData(key: string): Promise<any> {
          return cache[key] || (cache[key] = getFromServer(key)); 
      }
    

式ベースのプログラミングは命令型/コールバックベースのプログラミングよりも疎結合であるか、少なくとも同じ目標である構成可能性を追求していると主張できます。

12
Olmo

promiseは非同期操作の結果を表すオブジェクトです 。そのため、それを渡すことができ、柔軟性が高まります。

コールバックを使用する場合、非同期操作の呼び出し時に、処理方法、つまり結合を指定する必要があります。 promiseを使用すると、後で処理する方法を指定できます。

以下に例を示します。ajaxを介してデータをロードし、その間にロード中のページを表示したいとします。

コールバックあり:

void loadData = function(){
  showLoadingScreen();
  $.ajax("http://someurl.com", {
    complete: function(data){
      hideLoadingScreen();
      //do something with the data
    }
  });
};

戻ってくるデータを処理するコールバックは、hideLoadingScreenを呼び出す必要があります。

Promiseを使用すると、上記のスニペットを書き換えて読みやすくすることができ、hideLoadingScreenを完全なコールバックに配置する必要がありません。

約束あり

var getData = function(){
  showLoadingScreen();
  return $.ajax("http://someurl.com").promise().always(hideLoadingScreen);
};

var loadData = function(){
  var gettingData = getData();
  gettingData.done(doSomethingWithTheData);
}

var doSomethingWithTheData = function(data){
 //do something with data
};

UPDATE:私は ブログ投稿 を書きました。これは、追加の例を提供し、約束とは何か、どのように明確な説明を提供しますその使用は、コールバックの使用と比較できます。

49
Rui

操作は継続する方法を「知る」必要はなく、準備ができたときだけ知っていればよいので、約束があれば結合は緩やかになります。

コールバックを使用する場合、非同期操作は実際にはその継続ではなく、ビジネスへの参照を持ちます。

Promiseを使用すると、非同期操作で式を簡単に作成してから、解決方法を決定することもできます。

したがって、約束は、イベントの連鎖と実際の作業の懸念を区別するのに役立ちます。

27
harpo

約束は、何かに対する遅延応答の概念を具体化します。非同期計算を渡すことができるため、非同期計算を最上級の市民にします。必要に応じて、構造を定義できます。つまり、モナド構造です。その上に、コードを大幅に簡素化する高次のコンビネータを構築できます。

たとえば、promiseの配列を受け取り、配列のpromiseを返す関数を使用できます(通常、これはsequenceと呼ばれます)。これは非常に難しいか、コールバックでは不可能です。そして、このようなコンビネータはコードを簡単に記述できるだけでなく、読みやすくします。

質問に答えるために、逆に考えてみましょう。コールバックは、明確な構造と再利用性を約束するアドホックソリューションです。

5
edofic

そうではありません。これは、約束のポイントを完全に失っている人々が、コールバックを使用して書くよりもはるかに多くのコードを書くことを正当化するために使用する合理化です。これを行うことに明らかに利点がないことを考えると、少なくとも常にコードが結合されていないか何かを自分自身に伝えることができます。

実際の具体的な利点については、 約束とは何か、なぜ使用する必要があるか を参照してください。

4
Esailija