Promise.resolve проти нового Promise (вирішити)


92

Я використовую bluebird, і я бачу два способи вирішити синхронні функції в Promise, але я не отримую різниці між обома способами. Схоже, стек стежка трохи відрізняється, тому вони не просто alias, правда?

Отже, який спосіб є кращим?

Шлях А

function someFunction(someObject) {
  return new Promise(function(resolve) {
    someObject.resolved = true;
    resolve(someObject);
  });
}

Шлях Б

function someFunction(someObject) {
  someObject.resolved = true;
  return Promise.resolve(someObject);
}

2
Promise.resolveце просто цукор.
Qantas 94 Heavy

1
Коротка відповідь - відсутність різниці у використанні. Просто цукор.
Піналь

@Pinal Що таке "цукор"?
doubleOrt

5
@Телець. Синтаксичний цукор - це синтаксис, покликаний полегшити читання або вираження. див .: wikipedia .
Вік,

Відповіді:


82

На відміну від обох відповідей у ​​коментарях - різниця є.

Поки

Promise.resolve(x);

в основному те саме, що

new Promise(function(r){ r(x); });

є тонкість.

Функції повернення обіцянок, як правило, повинні мати гарантію того, що вони не повинні кидати синхронно, оскільки вони можуть виконувати асинхронно. Для запобігання несподіваних результатів та умов перегонів - кидки, як правило, перетворюються на повернені відмови.

Маючи це на увазі - коли була створена специфікація, конструктор обіцянок є безпечним.

Що якщо someObjectє undefined?

  • Шлях А повертає відхилену обіцянку.
  • Шлях В кидає синхронно.

Bluebird це побачив, і Петка додав Promise.methodвирішити цю проблему, щоб ви могли продовжувати використовувати повернені значення. Тож правильний і найпростіший спосіб написати це в Bluebird насправді не є ні тим, ні іншим - це:

var someFunction = Promise.method(function someFunction(someObject){
    someObject.resolved = true;
    return someObject;
});

Promise.method перетворить метання на відхилення та повернення на рішення для вас. Це найбільш безпечний спосіб зробити це, і він засвоює thenables через повернені значення, тому він би працював, навіть якщо someObjectнасправді це сама обіцянка.

Загалом, Promise.resolveвикористовується для відливання предметів та іноземних обіцянок (тенабле) до обіцянок. Це його варіант використання.


"Функції повернення обіцянок, як правило, мають гарантувати, що вони не повинні кидати синхронно, оскільки вони можуть здійснювати асинхронну передачу". Чи не могли б ви розширити питання, чому функції повинні бути синхронними або асинхронними, але не обома? В даний час мені подобається Promise.resolve (). Чи хочете ви зайти так далеко, сказавши, що використання Promise.resolve()- це анти-шаблон?
Ashley Coolman

2
@AshleyCoolman див. Blog.izs.me/post/59142742143/designing-apis-for-asynchrony - метод, який іноді поводиться асинхронно, завжди повинен робити це для послідовності.
Бенджамін Груенбаум

Чи Promise.resolve()створює новий екземпляр Promiseтак само, як і використання new? Якщо ні, то return Promise.resolve(yourCode)було б швидше і уникати синхронних кидків.
Стівен Вашон,

1
Мені погано, я використовую "Promise.resolve (). Потім (function () {/ * випадок, який може спричинити помилку * /}). Потім ...", щоб переконатися, що помилка стає відхиленою обіцянкою ... Я детальніше розгляну "Метод обіцянки"
Полополло,

1
@Polopollo або Promise.coroutineщо ще корисніше.
Бенджамін Груенбаум,

16

Є ще одна відмінність, про яку не згадують відповіді або коментарі вище:

Якщо someObjectце Promise, new Promise(resolve)буде коштувати два додаткових кліща.


Порівняйте два такі фрагменти коду:

const p = new Promise(resovle => setTimeout(resovle));

new Promise(resolve => resolve(p)).then(() => {
  console.log("tick 3");
});

p.then(() => {
  console.log("tick 1");
}).then(() => {
  console.log("tick 2");
});

const p = new Promise(resovle => setTimeout(resovle));

Promise.resolve(p).then(() => {
  console.log("tick 3");
});

p.then(() => {
  console.log("tick 1");
}).then(() => {
  console.log("tick 2");
});

Другий фрагмент спочатку надрукує "галочку 3". Чому?

  • Якщо значення є обіцянкою, Promise.resolve(value)поверне значення точно. Promise.resolve(value) === valueбуло б правдою. див. MDN

  • Але new Promise(resolve => resolve(value))повернув би нову обіцянку, яка замикається, щоб слідувати valueобіцянці. Для здійснення "блокування" потрібен додатковий один галочку.

    // something like:
    addToMicroTaskQueue(() => {
      p.then(() => {
        /* resolve newly promise */
      })
        // all subsequent .then on newly promise go on from here
        .then(() => {
          console.log("tick 3");
        });
    });

    tick 1 .thenВиклик буде працювати першим.


Список літератури:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.