web-dev-qa-db-ja.com

約束と継続の関係とは

私は約束が何であるかを理解していると思います、そして私は継続が何であるかについて理解していると思いますが、それでも彼らのつながりが何であるかはわかりません。 Promiseは継続をどのように使用しますか。彼らは決して戻らない。これは継続を使用しているという事実によって説明されるが、継続を操作するときに非常に特徴的な「ジャンプ」をいつ、なぜ行うのかはわからない。

3
hgiesel

TL; DR

関数への同期呼び出しの後に実行されるコードは、同じ関数を非同期で呼び出すときにpromiseに渡す継続になります。

詳細図

直感的に理解できるように、同期コードを非同期コードに変換する方法を次に示します。答え全体は非公式に書かれており、特定のプログラミング言語は考慮されていません。

同期コード:

actionsBeforeCall();
x = computeSomething();
actionsAfterCall(x);

これは、呼び出し前にいくつかのコードがあり、次に値xを返すことができる呼び出しがあり、次に変数xを介した呼び出しの結果に依存する可能性がある他のいくつかのコードがあることを概略的に示しています。もちろん、複数の変数(xyなど)が存在する場合や、変数がまったく存在しない場合がありますが、呼び出し後のアクションは、computeSomething( )。

呼び出しを非同期で実行する場合は、promiseを作成できます。

actionsBeforeCall();
p = promise(computeSomething);

Promiseは、将来いつか完了する計算を表すオブジェクトであるため、非同期計算を開始したスレッドは、それと通信するためのハンドルを保持できます。これで、メインスレッドは非同期で実行されているため、非同期関数が終了するのを待つのを停止しません。したがって、2つの問題があります。

  1. メインスレッドは、非同期計算の完了時に何をすべきかをどのように伝えますか?
  2. 非同期計算はどのように結果を返しますか?非同期計算は、それを呼び出したスレッドから切り離され、値を返すことができなくなりました。

継続は両方の問題を解決します:

  1. これは、非同期計算が完了したときに呼び出す必要がある関数です。
  2. 継続は、xによって返された結果を表す引数computeSomethingを取ります。または、いくつかのグローバル変数にアクセスして、computeSomethingによって生成された結果をフェッチします。

だからあなたはメインスレッドであなたが書く

actionsBeforeCall();
p = promise(computeSomething);
p.onComplete(actionsAfterCall)

最後の行は、computeSomethingが終了したら、関数actionsAfterCallを呼び出して結果を示すことを意味します。次に、actionsAfterCallは入力引数を取る必要があるため、promiseは内部的に次のような処理を実行できます。

x = computeSomething()

...

actionsAfterCall(x)

重要な点は、非同期計算では結果値を返さないということです。代わりに、計算の結果を継続に渡します。

5
Giorgio