В качестве примера предположим, что я хочу получить список файлов откуда-то, а затем загрузить содержимое этих файлов и, наконец, отобразить их пользователю. В синхронной модели это было бы что-то вроде этого (псевдокод):
var file_list = fetchFiles(source);
if (!file_list) {
display('failed to fetch list');
} else {
for (file in file_list) { // iteration, not enumeration
var data = loadFile(file);
if (!data) {
display('failed to load: ' + file);
} else {
display(data);
}
}
}
Это обеспечивает достойную обратную связь для пользователя, и я могу перемещать фрагменты кода в функции, если я так считаю нужным. Жизнь проста.
Теперь, чтобы раздавить мои мечты: fetchFiles()
и loadFile()
на самом деле асинхронны. Легкий выход - превратить их в синхронные функции. Но это плохо, если браузер блокируется, ожидая завершения вызовов.
Как я могу обрабатывать множественные взаимозависимые и/или многоуровневые асинхронные вызовы, не углубляясь глубже и глубже в бесконечную цепочку обратных вызовов, в классическом режиме редукции ad spaghettum? Существует ли проверенная парадигма для их четкой обработки при сохранении слабого кода?