Описание: Существуют ли какие-то хорошо зарекомендовавшие себя шаблоны наилучшей практики, которым я могу следовать, чтобы сохранить мой код читабельным, несмотря на использование асинхронного кода и обратных вызовов?
Я использую библиотеку JavaScript, которая делает много вещей асинхронно и сильно зависит от обратных вызовов. Кажется, что написание простого метода «load A, load B, ...» становится довольно сложным и трудным для понимания при использовании этого шаблона.
Позвольте мне привести (надуманный) пример. Допустим, я хочу загрузить кучу изображений (асинхронно) с удаленного веб-сервера. В 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
гарантирует, что пользовательский интерфейс остается отзывчивым), а затем кнопка «Пуск» снова включается.
В 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
это ваш ответ.