Мне нравится использовать обещания от Q :
Если функция не может вернуть значение или вызвать исключение без блокировки, она может вместо этого вернуть обещание. Обещание - это объект, представляющий возвращаемое значение или выброшенное исключение, которое функция может в конечном итоге предоставить. Обещание также можно использовать в качестве прокси для удаленного объекта, чтобы преодолеть задержку.
На первом проходе обещания могут смягчить «пирамиду гибели»: ситуацию, когда код движется вправо быстрее, чем вперед.
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
С библиотекой обещаний вы можете расплющить пирамиду.
Q.fcall(step1)
.then(step2)
.then(step3)
.then(step4)
.then(function (value4) {
// Do something with value4
}, function (error) {
// Handle any error from step1 through step4
})
.done();
При таком подходе вы также получаете неявное распространение ошибок, как try, catch и finally. Ошибка на шаге 1 переместится на шаг 5, где она перехватывается и обрабатывается.
Подход обратного вызова называется «инверсией управления». Функция, которая принимает обратный вызов вместо возвращаемого значения, говорит: «Не звони мне, я позвоню тебе». Обещает не инвертировать инверсию, четко отделяя входные аргументы от аргументов потока управления. Это упрощает использование и создание API-интерфейсов, в частности, переменных, аргументов отдыха и распространения.