09.Promises

7364 ワード

Promises
コールバック以外にも、Parse JavaScript SDKの非同期方法はすべてPromiseに戻ります.Promisesがあります.コードはコールバックを使うよりも簡潔です.
1.Promisesの紹介
PromisesはJavaScriptプログラミングにおける次の偉大なモデルを表しています.しかし、彼らがなぜこんなに偉大なのかを知ることは容易ではない.その核心はPromiseが任務の結果を代表しているので、すでに完成しても完成していないかもしれません.Promiseの唯一のインターフェース規定はthen関数があります.Promisesが成功したり失敗したりした時に、フィードバックを与えられます.これはCommon JS Promises/A proposalに関連した概要があります.例えば、Parse.Objectを保存することを考慮して、これは非同期的な動作である.古いコールバックの例では、コードは以下の通りです.
object.save({ key: value }, {
  success: function(object) {
    // the object was saved.
  },
  error: function(object, error) {
    // saving the object failed.
  }
});
新しいPromiseの例では、同じコードを下記に示します.
object.save({ key: value }).then(
  function(object) {
    // the object was saved.
  },
  function(error) {
    // saving the object failed.
  });
大きな違いはないですよね?何か大きなことがありますか?実は、Promisesの本当の強さは、それらを複数のチェーンで一緒に使うことができるところです.promise.thenを呼び出して、funcが完了するまで新しいPromisesを返します.しかし、funcの使い方にはとても特別なところがあります.thenに提供されたフィードバックが新たなPromisesに戻ると、thenが戻ってきたPromisesが満たされなくなります.以上の行為の詳細はPromises/A+Propsalに詳しく説明されています.これは複雑な話題ですが、一つの例がもっとはっきりしているかもしれません.
あなたがコードを作成して登録し、オブジェクトを見つけて更新していることを想像します.古いモデルでは、最終的にピラミッドコードというものが得られます.
Parse.User.logIn("user", "pass", {
  success: function(user) {
    query.find({
      success: function(results) {
        results[0].save({ key: value }, {
          success: function(result) {
            // the object was saved.
          }
        });
      }
    });
  }
});
これは非常に愚かに見えます.コードを間違えて処理していないからです.しかし、Promisesチェーンの働き方により、コードはよりフラット化されます.
Parse.User.logIn("user", "pass").then(function(user) {
  return query.find();
}).then(function(results) {
  return results[0].save({ key: value });
}).then(function(result) {
  // the object was saved.
});
あだいぶよくなりました
2.then方法
各Promiseには一対のフィードバックを持つthen方法があります.Promisesが解決されたら、最初のコールバックを呼び出し、Promisesが拒否されたら、第二のコールバックを呼び出します.
obj.save().then(function(obj) {
  // the object was saved successfully.
}, function(error) {
  // the save failed.
});
3.チェーンプロミックス
Promisesはちょっと不思議です.リンクを通して入れ子を避けました.Promisesのリピートが新しいPromisesに戻ると、最初のリピートは解決されなくなります.これは、リピートのようなピラミッドコードを使用することなく、複数の操作を実行させることができます.
var query = new Parse.Query("Student");
query.descending("gpa");
query.find().then(function(students) {
  students[0].set("valedictorian", true);
  return students[0].save();

}).then(function(valedictorian) {
  return query.find();

}).then(function(students) {
  students[1].set("salutatorian", true);
  return students[1].save();

}).then(function(salutatorian) {
  // Everything is done!

});
4.Promisesエラー処理
上記のコード例は簡単のためにエラー処理が発生していませんでしたが、それらを追加すると元のコールコードが混乱します.
Parse.User.logIn("user", "pass", {
  success: function(user) {
    query.find({
      success: function(results) {
        results[0].save({ key: value }, {
          success: function(result) {
            // the object was saved.
          },
          error: function(result, error) {
            // An error occurred.
          }
        });
      },
      error: function(error) {
        // An error occurred.
      }
    });
  },
  error: function(user, error) {
    // An error occurred.
  }
});
Promisesは、それらがすでに完了したかどうかや失敗したかどうかを知っているので、エラー処理プログラムに出会う前に任意のコールバック関数を呼び出すことなくエラーを伝えることができます.例えば、上のコードは簡単に書くことができます.
Parse.User.logIn("user", "pass").then(function(user) {
  return query.find();
}).then(function(results) {
  return results[0].save({ key: value });
}).then(function(result) {
  // the object was saved.
}, function(error) {
  // there was some error.
});
一般的に、開発者は失敗したPromisesは、例外的に例外的なステップを投げかけるのと同等であると考えています.実際に、thenに伝達されたコールバックがエラーを投げたら、戻ってきたこのエラーを伴うプロミセは失敗します.もしチェーン内の任意のPromiseがエラーを返したら、その後、すべての成功コールはスキップされます.エラーリカバリーはエラーを変換することができます.または拒否されていない新しいPromiseを返すことによって、このエラーを処理することができます.拒否されたPromisesを異常と見なすことができます.エラーリカバリはエラーを処理したり、エラーを投げ直したりできるcatchコードブロックのようです.
var query = new Parse.Query("Student");
query.descending("gpa");
query.find().then(function(students) {
  students[0].set("valedictorian", true);
  // Force this callback to fail.
  return Parse.Promise.error("There was an error.");

}).then(function(valedictorian) {
  // Now this will be skipped.
  return query.find();

}).then(function(students) {
  // This will also be skipped.
  students[1].set("salutatorian", true);
  return students[1].save();
}, function(error) {
  // This error handler WILL be called. error will be "There was an error.".
  // Let's handle the error by returning a new promise.
  return Parse.Promise.as("Hello!");

}).then(function(hello) {
  // Everything is done!
}, function(error) {
  // This isn't called because the error was already handled.
});
長い成功のリターンチェーンを持っています.最後にエラー処理プログラムだけの書き方はとても便利です.
5.Promisesを作成する
使用を開始すると、類似のfindまたはsave方法で戻ってきたらPromisesを使用します.でも、もっと高級なシーンについては、自分でプロミッズを書いてほしいかもしれません.Promiseを作成すると、reolveまたはrejectを呼び出して、そのフィードバックをトリガする必要があります.
var successful = new Parse.Promise();
successful.resolve("The good result.");

var failed = new Parse.Promise();
failed.reject("An error message.");
Promisesを作成しながら結果を知っているなら、より便利な方法があります.
var successful = Parse.Promise.as("The good result.");

var failed = Parse.Promise.error("An error message.");
6.シリアルタスクのPromises
一連のタスクを続けたいときは、タスクごとに前の完了を待ってから開始してください.Promisesは便利です.例えば、ブログのコメントをすべて削除したいと仮定します.
var query = new Parse.Query("Comments");
query.equalTo("post", post);

query.find().then(function(results) {
  // Create a trivial resolved promise as a base case.
  var promise = Parse.Promise.as();
  _.each(results, function(result) {
    // For each item, extend the promise with a function to delete it.
    promise = promise.then(function() {
      // Return a promise that will be resolved when the delete is finished.
      return result.destroy();
    });
  });
  return promise;

}).then(function() {
  // Every comment was deleted.
});
7.パラレルタスクのPromises
when法により、複数のタスクを並行して実行することもできます.複数の操作を一度に起動して、Parse.Promise.whenで新たなPromisesを作成します.すべての入力Promisesが解決されると、それは解決されます.もし入ってきたPromisesに失敗がなかったら、この新しいPromisesは成功します.そうでないと、最後のエラーで失敗します.並列実行動作はシリアル実行よりも速いが、システムリソースと帯域幅がより多く消費される可能性がある.
var query = new Parse.Query("Comments");
query.equalTo("post", post);

query.find().then(function(results) {
  // Collect one promise for each delete into an array.
  var promises = [];
  _.each(results, function(result) {
    // Start this delete immediately and add its promise to the list.
    promises.push(result.destroy());
  });
  // Return a new promise that is resolved when all of the deletes are finished.
  return Parse.Promise.when(promises);

}).then(function() {
  // Every comment was deleted.
});
8.非同期方法の作成
これらのツールを使って、Promisesに戻る非同期関数を簡単に実現できます.例えば、PromisesバージョンのsetTimeoutを実現することができます.
var delay = function(millis) {
  var promise = new Parse.Promise();
  setTimeout(function() {
    promise.resolve();
  }, millis);
  return promise;
};

delay(100).then(function() {
  // This ran after 100ms!
});