1) javascript と node.js を知らない人にとって「コールバック地獄」とは何ですか?
この他の質問には、Javascript コールバック地獄の例がいくつかあります: Node.js で非同期関数の長いネストを回避する方法
Javascript の問題は、計算を「フリーズ」し、「残りの部分」を後で (非同期的に) 実行する唯一の方法は、「残りの部分」をコールバック内に置くことです。
たとえば、次のようなコードを実行したいとします。
x = getData();
y = getMoreData(x);
z = getMoreData(y);
...
getData 関数を非同期にしたい場合、つまり値が返されるのを待っている間に他のコードを実行する機会を得たい場合はどうなるでしょうか? Javascript で唯一の方法は、継続渡しスタイルを使用して非同期計算に関係するすべてを書き直すことです。
getData(function(x){
getMoreData(x, function(y){
getMoreData(y, function(z){
...
});
});
});
このバージョンが前のバージョンよりも醜いということを誰かに納得させる必要はないと思います。:-)
2)「コールバック地獄問題」はいつ(どのような設定で)発生するのか?
コードにコールバック関数がたくさんある場合! コード内にそれらが増えるほど、それらを操作するのが難しくなり、ループ、try-catch ブロックなどを実行する必要がある場合は特に悪化します。
たとえば、私の知る限り、JavaScript で一連の非同期関数を実行する唯一の方法は、1 つが前の戻り値の後に実行される場合、再帰関数を使用することです。for ループは使用できません。
// we would like to write the following
for(var i=0; i<10; i++){
doSomething(i);
}
blah();
代わりに、次のように書く必要があるかもしれません:
function loop(i, onDone){
if(i >= 10){
onDone()
}else{
doSomething(i, function(){
loop(i+1, onDone);
});
}
}
loop(0, function(){
blah();
});
//ugh!
この種のことを行う方法を尋ねるStackOverflowでここに寄せられる質問の数は、それがどれほど混乱しているかを証明しています:)
3) なぜ発生するのか?
これが発生するのは、JavaScript で計算を遅延させて、非同期呼び出しが戻った後に実行する唯一の方法は、遅延コードをコールバック関数内に配置することであるために発生します。従来の同期スタイルで記述されたコードを遅延させることはできないため、あらゆる場所でネストされたコールバックが発生します。
4) または、シングル スレッド アプリケーションでも「コールバック地獄」が発生する可能性はありますか?
非同期プログラミングは並行性と関係があり、シングルスレッドは並列性と関係があります。2 つの概念は実際には同じものではありません。
シングル スレッド コンテキストで並行コードを使用することもできます。実際、コールバック地獄の女王である JavaScript はシングル スレッドです。
並行性と並列性の違いは何ですか?
5) RX がその単純な例で「コールバック地獄の問題」を解決する方法も示してください。
特に RX については何も知りませんが、通常、この問題はプログラミング言語に非同期計算のネイティブ サポートを追加することで解決されます。実装はさまざまで、async、ジェネレーター、コルーチン、callcc などがあります。
Python では、前のループの例を次のようなもので実装できます。
def myLoop():
for i in range(10):
doSomething(i)
yield
myGen = myLoop()
これは完全なコードではありませんが、アイデアは、誰かが myGen.next() を呼び出すまで、「yield」が for ループを一時停止するというものです。loop
重要なことは、再帰関数で行う必要があったように、ロジックを「裏返し」にする必要なく、for ループを使用してコードを記述できることです。