В чем разница между:
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 Promise.resolve("bbb");
})
.then(function(result) {
console.log(result);
});
Я спрашиваю, как меня разного поведения. Используя Angular и $http service с цепочкой .then(). Слишком много кода, следовательно, сначала пример выше.
Правило заключается в том, что если функция, которая находится в обработчике 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
возвращает обещание. +1 за спецификацию.
[[Resolve]]
называется , как на then
Ables и значение так , по существу она оборачивает значение с обещанием так return "aaa"
такой же , как return Promise.resolve("aaa")
и return Promise.resolve("aaa")
- это то же самое, что и return Promise.resolve(Promise.resolve("aaa"))
- так как return Promise.resolve(Promise.resolve("aaa"))
- идемпотент, вызов его значения более одного раза приводит к одному и тому же результату.
Оба ваших примера должны вести себя примерно одинаково.
Значение, возвращаемое внутри обработчика then()
, становится значением разрешения обещания, полученного от этого then()
. Если значение, возвращаемое внутри .then
, является обещанием, обещание, возвращенное then()
, "примет состояние" этого обещания и решит/отклонит так же, как это обещание.
В первом примере вы возвращаете "bbb"
в первом обработчике then()
, поэтому "bbb"
передается в следующий обработчик then()
.
Во втором примере вы возвращаете обещание, которое немедленно разрешено с помощью значения "bbb"
, поэтому "bbb"
передается в следующий обработчик then()
. (Promise.resolve()
здесь посторонний).
Результат тот же.
Если вы можете показать нам пример, который действительно демонстрирует различное поведение, мы можем сказать вам, почему это происходит.
Promise.resolve();
против return;
?
undefined
вместо "bbb"
.
Проще говоря, внутри функции обработчика 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.
У вас уже есть хороший формальный ответ. Я решил, что должен добавить короткий.
Следующие вещи идентичны с 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) и облегчает вашу жизнь. Всякий раз, когда может возникать разрешение обещания, возникает резолюция, создающая общую согласованность.
Promise.resolve()
во втором примере неPromise.resolve()
.then
обработчика нет ничего плохого, на самом деле, это ключевой аспект спецификации обещаний, что вы можете это сделать.