web-dev-qa-db-ja.com

Promiseからデータを抽出する方法

データを返す約束があり、変数に保存したいです。非同期の性質のため、JavaScriptでこれは不可能ですか?onResolveをコールバックとして使用する必要がありますか?

何らかの方法でこれを使用できますか(例:async/awaitでラップします):

const { foo, bar } = Promise.then(result => result.data, errorHandler);
// rest of script

これの代わりに?

Promise.then(result => {
   const { foo, bar } = result.data;
   // rest of script
 }, errorHandler);

注:ネイティブ実装の代わりにBluebirdライブラリが使用され、Promiseからasnyc/awaitまたはGeneratorsに変更することはできません。

15
Tobias Mühl

いいえ、データを取得することはできません同期的にあなたの例で提案しているような約束から外れています。データはコールバック関数内で使用する必要があります。あるいは、関数型プログラミングスタイルでは、promiseデータを map()ed over にすることができます。

async/await (素晴らしいはずです)を使用して問題がなければ、約束の非同期性を保持しながら同期的に見えるコードを書くことができます(@loganfsmythコメントを参照)。

const { foo, bar }  = await iAmAPromise.then(result => result.data);

全体として、すでにES6を使用しているので、トランスパイラーも使用していると思います。その場合、必ずasync/awaitを試してください。今日のように、まだ批准された仕様ではないという決定に重みを付けてください。

22
silkAdmin

非同期関数内の待機中のPromiseから値を取得できますが(関数を一時停止して結果を待機するため)、Promiseから直接値を取得してPromise自体と同じスコープに戻すことはできません。

これは、「out of」は、将来存在するもの(最終的に解決された値)を取得して、コンテキストに入れる(同期変数の割り当て)ことを意味するためです既に過去に発生した

つまり、タイムトラベルです。そして、たとえタイムトラベルが可能であったとしても、タイムトラベルは非常に混乱する可能性があるので、おそらく良いコーディング慣行ではないでしょう。:)

一般的に、これを行う必要があると感じた場合は、何かをリファクタリングする必要があることを示す良い兆候です。ここで "result => result.data"で何をしているのかに注意してください:

Promise.then(result => result.data, errorHandler);
// rest of script

..is already関数に渡すことで値を操作する(文字通り、マッピングする)場合。しかし、「//スクリプトの残り」がこの値に関連する重要なことを行うと仮定すると、おそらくcontinue現在更新された値をさらに別の関数でマッピングし、副作用を引き起こす値を使用して(画面にデータを表示するなど)。

Promise
    .then(result => result.data)
    .then(data => doSomethingWithData)// rest of script
    .catch(errorHandler);

「doSomethingWithData」は、将来の未知の時点で呼び出されます(if呼び出されます)。そのため、そのすべての動作を特定の関数に明確にカプセル化し、その関数をPromiseチェーンにフックするのが良い習慣です。

正直なところ、この方法の方が優れています。なぜなら、willが発生する特定のイベントシーケンスを明確に宣言する必要があるからです。

別の言い方をすれば、グローバルなトップレベルのスコープで仮想的に実行されるこのシナリオを想像してください。

const { foo, bar } = Promise.then(result => result.data, errorHandler);
console.log(foo);
//...more program

そこで何が起こると思いますか? 2つの可能性がありますが、どちらも悪いです。

  1. プログラム全体がhaveを停止し、Promiseが実行されるのを待ってから、「foo」と「bar」がどうなるかを知ることができます...いや、might。 (これは、非同期関数内の「待機」が実際に行うことです:値が利用可能になるか、エラーがスローされるまで関数の実行全体を一時停止します)
  2. fooとbarは未定義です(これは実際に発生することです)。なぜなら、同期的に実行されると、トップレベルのPromiseオブジェクト(それ自体は「値」ではなく、 getting最終値ORエラー)の周りの準モナディックラッパーdoes n'tはまだ値を含んでいる可能性が高い。
5
Dtipson