説明している問題は2つあります。
- あなたが書いているプログラムは外部から見たとき全体として非同期に振る舞うべきです。
- 関数呼び出しが制御を放棄する可能性があるかどうかにかかわらず、呼び出しサイトで表示されるべきではありません。
これを実現するにはいくつかの方法がありますが、基本的には
- 複数のスレッドを持つ(ある抽象化レベルで)
- 言語レベルで複数の種類の機能を持ち、それらはすべてこのように呼び出され
foo(4, 7, bar, quux)
ます。
(1)では、複数のプロセスをフォークして実行し、複数のカーネルスレッドを生成し、言語ランタイムレベルのスレッドをカーネルスレッドにスケジュールするグリーンスレッドの実装をまとめています。問題の観点からは、それらは同じです。この世界では、スレッドの観点から制御を放棄したり、制御を失ったりする機能はありません。スレッド自体は時々コントロールを持っていないと、時々実行されていないが、あなたはこの世界で独自のスレッドの制御をあきらめないでください。このモデルに適合するシステムは、新しいスレッドを生成したり、既存のスレッドに参加したりする機能を持つ場合と持たない場合があります。このモデルに適合するシステムには、Unixのようなスレッドを複製する機能がある場合とない場合がありますfork
。
(2)興味深いです。それを正すために、私たちは導入と排除の形について話す必要があります。
await
Javascriptのような言語に暗黙的に下位互換性のある方法で追加できない理由を示します。基本的な考え方は、約束をユーザーに公開し、同期コンテキストと非同期コンテキストを区別することにより、同期と非同期の関数を均一に処理できない実装の詳細をJavascriptが漏らしたということです。またawait
、非同期関数本体の外部で約束をすることはできないという事実もあります。これらの設計の選択は、「呼び出し側に非同期性を見えなくする」と互換性がありません。
ラムダを使用して同期関数を導入し、関数呼び出しで同期関数を削除できます。
同期機能の紹介:
((x) => {return x + x;})
同期機能の除去:
f(4)
((x) => {return x + x;})(4)
これを非同期関数の導入と削除と比較できます。
非同期機能の紹介
(async (x) => {return x + x;})
非同期関数の削除(注:async
関数内でのみ有効)
await (async (x) => {return x + x;})(4)
ここでの基本的な問題は、非同期関数がpromiseオブジェクトを生成する同期関数でもあるということです。
node.js replで非同期関数を同期的に呼び出す例を次に示します。
> (async (x) => {return x + x;})(4)
Promise { 8 }
仮に、動的に型付けされた言語であっても、非同期関数呼び出しと同期関数呼び出しの違いが呼び出しサイトで見えず、場合によっては定義サイトで見えない言語を持つことができます。
そのような言語をJavascriptに変換することは可能ですが、すべての機能を効果的に非同期にする必要があります。