Podsumowanie: Czy istnieją pewne sprawdzone wzorce najlepszych praktyk, które mogę stosować, aby mój kod był czytelny pomimo korzystania z kodu asynchronicznego i funkcji zwrotnych?
Korzystam z biblioteki JavaScript, która wykonuje wiele czynności asynchronicznie i w dużej mierze opiera się na wywołaniach zwrotnych. Wydaje się, że napisanie prostej metody „load A, load B, ...” staje się dość skomplikowane i trudne do naśladowania przy użyciu tego wzorca.
Dam (wymyślony) przykład. Powiedzmy, że chcę załadować kilka obrazów (asynchronicznie) ze zdalnego serwera WWW. W C # / async napisałbym coś takiego:
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();
Układ kodu przebiega zgodnie z „przebiegiem zdarzeń”: najpierw przycisk uruchamiania jest wyłączony, następnie obrazy są ładowane ( await
zapewnia, że interfejs użytkownika pozostaje responsywny), a następnie przycisk uruchamiania jest ponownie włączony.
W JavaScript, używając wywołań zwrotnych, wymyśliłem to:
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);
Myślę, że wady są oczywiste: musiałem przerobić pętlę na wywołanie rekurencyjne, kod, który powinien zostać wykonany na końcu, znajduje się gdzieś w środku funkcji, kod rozpoczynający pobieranie ( loadImage(0)
) znajduje się na samym dole, i ogólnie jest o wiele trudniej czytać i śledzić. Jest brzydka i nie podoba mi się.
Jestem pewien, że nie jestem pierwszym, który napotkał ten problem, więc moje pytanie brzmi: czy są jakieś dobrze ugruntowane wzorce najlepszych praktyk, które mogę zastosować, aby mój kod był czytelny pomimo korzystania z kodu asynchronicznego i wywołań zwrotnych?
LoadImageAsync
w rzeczywistości jest połączeniem Ext.Ajax.request
z Sencha Touch.
async.waterfall
to twoja odpowiedź.