В чем разница между:
new Promise(function(res, rej) {
res("aaa");
})
.then(function(result) {
return "bbb";
})
.then(function(result) {
console.log(result);
});
В чем разница между:
new Promise(function(res, rej) {
res("aaa");
})
.then(function(result) {
return "bbb";
})
.then(function(result) {
console.log(result);
});
Правило заключается в том, что если функция, которая находится в обработчике then
, возвращает значение, обещание разрешает/отклоняет с этим значением, и если функция возвращает обещание, что произойдет, следующее предложение then
будет быть предложением then
обещания возвращенной функции, поэтому в этом случае первый пример проходит через обычную последовательность thens
и выводит значения, как можно было бы ожидать, во втором примере - объект обещания, который возвращается, когда вы делаете Promise.resolve("bbb")
, а затем then
, который вызывается при цепочке (для всех целей и целей). Способ, которым он фактически работает, описан ниже более подробно.
Цитата из спецификации Promises/A +:
Процедура разрешения обещаний - абстрактная операция, принимающая в качестве вклада обещание и значение, которое мы обозначаем как
[[Resolve]](promise, x)
. Еслиx
является допустимым, он пытается обещать, принимая состояниеx
, в предположении, что x ведет себя, по крайней мере, как обещание. В противном случае он выполняет обещание со значениемx
.Эта обработка thenables позволяет реализовать реализацию обещаний, если они выставляют метод Promises/A + -compliant. Он также позволяет реализациям Promises/A + "ассимилировать" несоответствующие реализации с помощью разумных методов.
Ключевая вещь, которую следует отметить здесь, - это строка:
если
x
является обещанием, принять его состояние [3.4]
Оба ваших примера должны вести себя примерно одинаково.
Значение, возвращаемое внутри обработчика then()
, становится значением разрешения обещания, полученного от этого then()
. Если значение, возвращаемое внутри .then
, является обещанием, обещание, возвращенное then()
, "примет состояние" этого обещания и решит/отклонит так же, как это обещание.
В первом примере вы возвращаете "bbb"
в первом обработчике then()
, поэтому "bbb"
передается в следующий обработчик then()
.
Во втором примере вы возвращаете обещание, которое немедленно разрешено с помощью значения "bbb"
, поэтому "bbb"
передается в следующий обработчик then()
. (Promise.resolve()
здесь посторонний).
Результат тот же.
Если вы можете показать нам пример, который действительно демонстрирует различное поведение, мы можем сказать вам, почему это происходит.
У вас уже есть хороший формальный ответ. Я решил, что должен добавить короткий.
Следующие вещи идентичны с Promises/A + promises:
Promise.resolve
(В вашем случае Angular, который $q.when
)new $q
.then
.Таким образом, для обетования или простого значения X следующие значения:
Promise.resolve(x);
new Promise(function(resolve, reject){ resolve(x); });
Promise.resolve().then(function(){ return x; });
Promise.all([x]).then(function(arr){ return arr[0]; });
И неудивительно, что спецификация promises основана на процедуре разрешения Promise, которая позволяет легко взаимодействовать между библиотеками (например, $q и native promises) и облегчает вашу жизнь. Всякий раз, когда может возникать разрешение обещания, возникает резолюция, создающая общую согласованность.
Проще говоря, внутри функции обработчика then
:
A) Когда x
- значение (число, строка и т.д.):
return x
эквивалентен return Promise.resolve(x)
throw x
эквивалентен return Promise.reject(x)
B) Когда x
- это обещание, которое уже установлено (не ожидалось):
return x
эквивалентен return Promise.resolve(x)
, если обещание уже разрешено.return x
эквивалентен return Promise.reject(x)
, если Promise уже отклонен. C) Когда x
- это обещание, которое ожидает:
return x
вернет ожидающее обещание, и оно будет оценено на следующем then
.Подробнее об этом читайте в Promise.prototype.then() docs.