[解決済み] コールバック地獄とは何か、RXはそれをどのように、そしてなぜ解決するのか?
質問
JavaScriptやnode.jsを知らない人のために、コールバック地獄とは何か、簡単な例とともに明確な定義をしていただけないでしょうか。
どのような場合に(どのような設定において)コールバック地獄が発生するのでしょうか?
なぜ発生するのでしょうか?
コールバック地獄は、常に非同期計算と関係しているのでしょうか?
それともシングルスレッドアプリケーションでもコールバック地獄は起こりうるのでしょうか?
CourseraのReactive Courseを受講しましたが、Erik Meijerは講義の中で、RXが"callback hell"の問題を解決してくれると言いました。私はCourseraのフォーラムで"callback hell"とは何かを尋ねましたが、明確な回答は得られませんでした。
簡単な例で"callback hell"を説明した後、その簡単な例でRXが"callback hell problem"をどう解決するのかも教えてください。
どのように解決するのですか?
1) javascriptやnode.jsを知らない人にとって、quot;コールバック地獄とは何でしょうか?
この他の質問には、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) いつ (どのような設定で) "コールバック地獄問題" が発生するのでしょうか。
コールバック関数がたくさんあるときです。コード内にコールバック関数が多ければ多いほど扱いが難しくなり、ループやトライキャッチブロックなどが必要な場合は特にひどくなります。
例えば、私の知る限り、JavaScriptでは一連の非同期関数を実行する唯一の方法は、前の関数が戻った後に実行される再帰的な関数を使うことです。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について特に何も知りませんが、通常この問題は、プログラミング言語の非同期計算のネイティブサポートを追加することで解決されます。実装はさまざまで、非同期、ジェネレーター、コルーチン、および callcc が含まれます。
Pythonでは、前のループの例を次のようなもので実装することができます。
def myLoop():
for i in range(10):
doSomething(i)
yield
myGen = myLoop()
これは完全なコードではありませんが、誰かが myGen.next() を呼び出すまで "yield" が for ループを一時停止させるということです。重要なのは、for ループを使用してもコードを書くことができるということです。
loop
関数のようにロジックを裏返す必要がないことです。
関連
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] なぜGoogleはJSONレスポンスにwhile(1);を前置するのでしょうか?
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] 私のJavaScriptコードは "No 'Access-Control-Allow-Origin' header is present on requested resource "というエラーを受け取りますが、Postmanはそうならないのはなぜですか?
-
[解決済み] JSONPとは何か、なぜ作られたのか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] なぜ ++[[]][+[] +[+[]] は "10" という文字列を返すのでしょうか?
-
[解決済み] コールバック内で正しい `this` にアクセスする方法
-
[解決済み】PromiseとObservablesの違いは何ですか?
-
[解決済み] Chromeのwebkitインスペクタで「Unsafe JavaScript attempt to access frame with URL...」というエラーが継続的に発生する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 並行処理と並列処理の違いは何ですか?
-
[解決済み] Node.jsで非同期関数の長いネストを回避する方法
-
[解決済み] reactのrender関数でdynamic hrefを作成するには?
-
[解決済み] 文字列のn番目の出現箇所を取得するには?
-
[解決済み] モバイルWeb HTML5フレームワークの選び方【終了しました
-
[解決済み] JSXとLoadshを使用して、ある要素をn回繰り返す方法
-
[解決済み] javascriptで文字列から関数を作成する方法はありますか?
-
[解決済み] jQueryで入力ファイルが空かどうかをチェックする方法
-
[解決済み] javascriptでオプションのパラメータを扱う
-
[解決済み] Fetch: ステータスがOKでない場合、プロミスを拒否し、エラーをキャッチするか?