Каждый вызов .then()
возвращает новое обещание, что имеет свои собственные .then()
обработчиков. Это обещание автоматически связано с предыдущим обещанием, поэтому, когда предыдущее обещание полностью завершено с помощью собственного обработчика .then()
и что обработчик .then()
не вернул обещание, или если это произошло, когда обещание, которое оно вернуло, разрешено, оно может затем запустить следующий обещание в цепочке, которая должна быть решена, заставляя ее повторять цикл для своих обработчиков .then()
.
Ключ в том, что p.then()
возвращает новое обещание, которое само по себе разрешено, когда выполнено p.then()
, чтобы затем запустить следующий шаг в цепочке p.then().then()
и так далее.
Имейте в виду, что .then()
обработчик может сделать одну из четырех вещей:
- Возврат ничего (то же самое, как возвращение
undefined
).
- Вернуть значение
- Возвращение обещание
- Бросьте исключение
Для первых двух (возвращающей значение), то это просто означает, что .then()
обработчик выполняется, а затем следующий в цепочке может быть запущен.
При возвращении обещания, это обещание связано с обработчиками .then()
, поэтому его можно контролировать. Если/когда он разрешается, цепочка продолжается. Если/когда он отклоняется, цепь отклоняется. Обещание, которое возвращается, уже может быть разрешено или отклонено или может быть разрешено или отклонено в будущем, нет значимой разницы в поведении. Если возвращенное обещание никогда не будет разрешено или отклонено, цепочка обещаний застопорилась и не будет продолжаться до тех пор, пока она не будет разрешена или отвергнута (как и любое обещание).
Если обработчик .then()
выбрасывает исключение, это улавливается оберткой .then()
, и оно автоматически преобразуется в отклоненное обещание, за исключением причины отклонения.
Например, если я вставлял setTimeout на секунду, то цепочка продолжается и печатается не по порядку.
Вы не можете эффективно использовать setTimeout()
самостоятельно, чтобы отложить цепочку обещаний. Вместо этого вам нужно вернуть обещание от обработчика .then()
, который разрешен после некоторого времени таймаута. Bluebird имеет .delay(x)
, который делает это за вас.
Или, вы можете написать его самостоятельно, если не используется Bluebird:
function delay(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
fn().then(function() {
// delay promise chain by 1000ms
return delay(1000);
}).then(function() {
// promise chain continues here
});
Или, с Bluebird обещаниями, это так просто, как:
fn().delay(1000).then(function() {
delayed promise chain continues here
});
Это то же самое, как делать что-то вроде 'Promise. решимость (нуль) .then (независимо) '. Если в обещании нет реальной задачи, обещание немедленно решается. – m0meni
@ AR7 Как бы вы решили добавить таймаут в этом случае? [Документы для '.timeout'] (http://bluebirdjs.com/docs/api/timeout.html) заставляют выглядеть так, как будто вы можете просто поставить' .timeout (1000) 'между' then', но это не работает. – 1252748
Вам может понравиться это, http://www.mattgreer.org/articles/promises-in-wicked-detail/ –