概要:非同期コードとコールバックを使用しているにもかかわらず、コードを読みやすくするために使用できる、確立されたベストプラクティスのパターンはありますか?
非同期に多くのことを行い、コールバックに大きく依存するJavaScriptライブラリを使用しています。単純な "load A、load B、..."メソッドを書くのはかなり複雑になり、このパターンを使用するのは難しいようです。
(不自然な)例を挙げましょう。リモートWebサーバーから一連の画像を(非同期で)ロードしたいとします。C#/ asyncでは、次のように記述します。
disableStartButton();
foreach (myData in myRepository) {
var result = await LoadImageAsync("http://my/server/GetImage?" + myData.Id);
if (result.Success) {
myData.Image = result.Data;
} else {
write("error loading Image " + myData.Id);
return;
}
}
write("success");
enableStartButton();
コードレイアウトは「イベントのフロー」に従います。最初に、開始ボタンが無効になり、次に画像が読み込まれ(await
UIの応答性が維持されます)、その後、開始ボタンが再び有効になります。
JavaScriptでは、コールバックを使用して、これを思いつきました:
disableStartButton();
var count = myRepository.length;
function loadImage(i) {
if (i >= count) {
write("success");
enableStartButton();
return;
}
myData = myRepository[i];
LoadImageAsync("http://my/server/GetImage?" + myData.Id,
function(success, data) {
if (success) {
myData.Image = data;
} else {
write("error loading image " + myData.Id);
return;
}
loadImage(i+1);
}
);
}
loadImage(0);
欠点は明らかだと思います:ループを再帰呼び出しに作り直す必要がありました。最後に実行されるはずのコードは、関数の途中のどこかにあり、ダウンロードを開始するコード(loadImage(0)
)は一番下にあります。そしてそれは一般的に読み、従うのがはるかに困難です。醜くて気に入らない。
私がこの問題に最初に遭遇したのは自分ではないと確信しているので、私の質問は、非同期コードとコールバックを使用しているにもかかわらず、コードを読みやすくするために使用できる、確立されたベストプラクティスのパターンはありますか?
LoadImageAsync
あり、実際にExt.Ajax.request
はSencha Touch への呼び出しです。
async.waterfall
あなたの答えです。