В чем разница между возвращаемым значением или Promise.resolve от then ()

240

В чем разница между:

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(). Слишком много кода, следовательно, сначала пример выше.

  • 1
    Какое «другое поведение» вы видите? Оба примера должны работать и вести себя примерно одинаково. Promise.resolve() во втором примере не Promise.resolve() .
  • 4
    @pixelbits В возврате обещания от then обработчика нет ничего плохого, на самом деле, это ключевой аспект спецификации обещаний, что вы можете это сделать.
Показать ещё 2 комментария
Теги:
promise
q

4 ответа

109

Правило заключается в том, что если функция, которая находится в обработчике 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]

ссылка: https://promisesaplus.com/#point-49

  • 3
    «Принять его состояние» - это краткий и полезный способ выражения поведения, когда обработчик then возвращает обещание. +1 за спецификацию.
  • 59
    На самом деле - соответствующая часть спецификации здесь является тот факт , что [[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")) - идемпотент, вызов его значения более одного раза приводит к одному и тому же результату.
Показать ещё 2 комментария
75

Оба ваших примера должны вести себя примерно одинаково.

Значение, возвращаемое внутри обработчика then(), становится значением разрешения обещания, полученного от этого then(). Если значение, возвращаемое внутри .then, является обещанием, обещание, возвращенное then(), "примет состояние" этого обещания и решит/отклонит так же, как это обещание.

В первом примере вы возвращаете "bbb" в первом обработчике then(), поэтому "bbb" передается в следующий обработчик then().

Во втором примере вы возвращаете обещание, которое немедленно разрешено с помощью значения "bbb", поэтому "bbb" передается в следующий обработчик then(). (Promise.resolve() здесь посторонний).

Результат тот же.

Если вы можете показать нам пример, который действительно демонстрирует различное поведение, мы можем сказать вам, почему это происходит.

  • 1
    Хороший ответ! Что насчет Promise.resolve(); против return; ?
  • 1
    @FabianTe Они также будут иметь тот же эффект, за исключением undefined вместо "bbb" .
39

Проще говоря, внутри функции обработчика 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.

39

У вас уже есть хороший формальный ответ. Я решил, что должен добавить короткий.

Следующие вещи идентичны с Promises/A + promises:

  • Вызов Promise.resolve (В вашем случае Angular, который $q.when)
  • Вызов конструктора обещаний и разрешение в его резольвере. В вашем случае new $q.
  • Возврат значения из обратного вызова then.
  • Вызов Promise.all по массиву со значением и извлечению этого значения.

Таким образом, для обетования или простого значения 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) и облегчает вашу жизнь. Всякий раз, когда может возникать разрешение обещания, возникает резолюция, создающая общую согласованность.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню