JavaScriptのDeferred、Promise、Futureの違いは何ですか?
-
22-10-2019 - |
質問
延期、約束、未来の違いは何ですか?
これら3つすべての背後に一般的に承認された理論はありますか?
解決
OPの質問にどのように答えようとしたかについての明らかな嫌悪感に照らして。文字通りの答えは、約束は他のオブジェクトと共有されたものであり、延期されたものはプライベートに保つべきです。主に、延期された(一般的に約束を拡大する)は、それ自体を解決することができますが、約束はそうすることができないかもしれません。
あなたがminutiaeに興味があるなら、調べてください 約束/a+.
私が知る限り、包括的な目的は、標準化されたインターフェイスを介した明確さを改善し、カップリングを緩めることです。見る 提案された読書 @jfriend00から:
コールバックを関数に直接渡すのではなく、緊密に結合されたインターフェイスにつながる可能性のあるもので、約束を使用することで、同期または非同期のコードの懸念を分離できます。
個人的には、非同期リクエスト、依存関係のネットワークを持つスクリプトをロードするテンプレートを扱う場合、特に役立つのが特に役立つことがわかりました。
確かに、JSモードでCodemirrorを非同期にロードした後に何かをするという純粋なコールバック形式を比較してください(謝罪、私はjqueryを使用していません その間):
/* assume getScript has signature like: function (path, callback, context)
and listens to onload && onreadystatechange */
$(function () {
getScript('path/to/CodeMirror', getJSMode);
// onreadystate is not reliable for callback args.
function getJSMode() {
getScript('path/to/CodeMirror/mode/javascript/javascript.js',
ourAwesomeScript);
};
function ourAwesomeScript() {
console.log("CodeMirror is awesome, but I'm too impatient.");
};
});
Promises dubraturedバージョンに(繰り返しますが、謝罪、私はjqueryの最新ではありません):
/* Assume getScript returns a promise object */
$(function () {
$.when(
getScript('path/to/CodeMirror'),
getScript('path/to/CodeMirror/mode/javascript/javascript.js')
).then(function () {
console.log("CodeMirror is awesome, but I'm too impatient.");
});
});
セミプソードコードについて謝罪しますが、コアのアイデアがやや明確になることを願っています。基本的に、標準化された約束を返すことにより、約束を渡すことができ、より明確なグループ化を可能にすることができます。
他のヒント
選択された回答を含むこれらの回答は、概念的に約束を導入するのに適していますが、ライブラリを実装するときに生じる用語の違いの正確な違いの詳細に欠けています(そしてそこでそれは 重要な違い)。
まだあるので 進化する仕様, 、答えは現在、両方の参照を調査しようとすることから来ています( ウィキペディア)および実装(次のような jquery):
延期: :人気のある参照で説明したことはありません、 1 2 3 4 しかし、実装によって約束の解決の仲裁人として一般的に使用されます(実装
resolve
とreject
). 5 6 7時には延期されることも約束です(実装
then
), 5 6 それ以外の場合は、解決のみが繰り返される方が純粋であると見なされ、ユーザーに使用の約束にアクセスするように強制しますthen
. 7約束: :議論中の戦略のための最も包括的な言葉。
抽象性を抽象化したいターゲット関数の結果を保存するプロキシオブジェクトに加えて、
then
関数別のターゲット関数を受け入れ、新しい約束を返します。 2の例 commonjs:
> asyncComputeTheAnswerToEverything() .then(addTwo) .then(printResult); 44
常に人気のある参考文献で説明されていますが、誰の責任解決が該当するかについては決して指定されていません。 1 2 3 4
未来: :いくつかの一般的な参考文献で見つかった一見控えめな用語 1 少なくとも1つの一般的な実装、 8 しかし、「約束」という用語の好みで議論を段階的に廃止されているように見える 3 トピックに関する一般的な紹介で常に言及されているわけではありません。 9
ただし、少なくとも1つのライブラリは、同期性とエラー処理を抽象化するために一般的に用語を使用しますが、提供していません。
then
機能。 10 「約束」という用語を避けることが意図的なものであるかどうかは不明ですが、おそらく約束が「shensables」を中心に構築されているため、良い選択です。 2
参照
- 約束と未来のウィキペディア
- 約束/a+仕様
- 約束に関するDOM標準
- DOM Standard Promise Spec Wip
- Dojo Toolkitの延期
- jQueryが延期されます
- Q
- Futurejs
- 約束に関する機能的なJavaScriptセクション
- AngularJS統合テストの先物
潜在的に物事を混乱させる可能性があります
-
(tl; dr、promises/a+は主に約束のあいまいさを解決します/a)
本当にクリックしたのは、私にとってクリックしました このプレゼンテーション Domenic Denicolaによる。
で github gist, 、彼は私が一番好きな説明を与えました、それは非常に簡潔です:
約束のポイントは、非同期の世界で機能的な構成と誤りを返すことです。
言い換えれば、約束は私たちに書くことができる方法です 非同期 まるでそうであるかのように書くのがほぼ簡単なコード 同期.
約束を伴うこの例を考えてみましょう。
getTweetsFor("domenic") // promise-returning async function
.then(function (tweets) {
var shortUrls = parseTweetsForUrls(tweets);
var mostRecentShortUrl = shortUrls[0];
return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
})
.then(doHttpRequest) // promise-returning async function
.then(
function (responseBody) {
console.log("Most recent link text:", responseBody);
},
function (error) {
console.error("Error with the twitterverse:", error);
}
);
この同期コードを書いているかのように機能します。
try {
var tweets = getTweetsFor("domenic"); // blocking
var shortUrls = parseTweetsForUrls(tweets);
var mostRecentShortUrl = shortUrls[0];
var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
console.log("Most recent link text:", responseBody);
} catch (error) {
console.error("Error with the twitterverse: ", error);
}
(これがまだ複雑に聞こえる場合は、そのプレゼンテーションを見てください!)
延期に関しては、それは方法です .resolve()
また .reject()
約束。の中に 約束/b スペック、それは呼ばれます .defer()
. 。 jqueryでは、そうです $.Deferred()
.
私の知る限り、少なくともjQuery 1.8.2のように、jQueryでの約束の実装が壊れていることに注意してください(その要点を参照)。
おそらく実装しています 約束/香り, 、しかし、「非同期の試行/キャッチ」機能が機能しないという意味で、正しいエラー処理が必要です。 Asyncコードを使用して「Try/Catch」を持つことは全くクールなので、これは残念です。
約束を使用する場合(自分のコードで試してみてください!) クリス・コワルのq. 。 jQueryバージョンは、クリーナーjQueryコードを書くためのコールバックアグリゲーターにすぎませんが、ポイントを見逃しています。
将来に関しては、私は知りません、私はそれをどのAPIでも見ていません。
編集: Domenic DenicolaのYouTubeは約束について話します から @農場以下のコメント。
マイケルジャクソンからの引用(はい、 マイケルジャクソン)ビデオから:
私はあなたにあなたの心の中でこのフレーズを燃やしてほしい: 約束はです 非同期値.
これは優れた説明です。約束は、未来の変数のようなものです。ある時点で存在する(または発生する)ものへの一流の言及です。
a 約束 約束が作成されたときに必ずしもわかっていない値のプロキシを表します。これにより、ハンドラーを非同期アクションの最終的な成功価値または失敗の理由に関連付けることができます。これにより、非同期メソッドは同期メソッドのような値を返すことができます。最終的な値の代わりに、非同期メソッドは将来のある時点で値を持つという約束を返します。
https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/promise
deferred.promise()
方法により、非同期関数が他のコードが内部要求の進行状況やステータスを妨害するのを防ぐことができます。約束は、追加のハンドラーを添付したり、状態を決定するために必要な延期方法のみを公開します(その後、完了、失敗、常に、パイプ、進行、状態、約束)、しかし状態を変えるものではありません(解決、拒否、通知、解決、拒否、および通知).
ターゲットが提供されている場合、 deferred.promise()
メソッドをそれに取り付けてから、新しいオブジェクトを作成するのではなく、このオブジェクトを返します。これは、すでに存在するオブジェクトに約束の動作を取り付けるのに役立ちます。
延期されている場合は、延期者への参照を維持して、ある時点で解決または拒否できるようにしてください。 deferred.promise()を介してPromiseオブジェクトのみを返します。これにより、他のコードがコールバックを登録したり、現在の状態を検査したりできます。
単に私たちはそれを言うことができます 約束 まだどこにも知られていない値を表します 延期 まだ終わっていない作業を表します。
- a
promise
まだ知られていない値を表します - a
deferred
まだ終わっていない作業を表します
約束は、最初は不明である結果のプレースホルダーですが、延期は値を生じる計算を表します。
参照