Когда я должен вызывать Promise.resolve() напрямую?

Я видел, что родной ES6 Promise.resolve() можно вызывать напрямую — как статический метод. Facebook использует его таким образом в своих примерах Flux.

Но в каком случае мне это делать? Ставить что-то в очередь? Или вместо использования window.setTimeout()?


person kraftwer1    schedule 08.09.2015    source источник


Ответы (3)


Вы должны вызывать Promise.resolve(object), когда вам нужно создать обещание, которое уже разрешено. Например, у вас может быть функция, которая запускает загрузку ресурса с сервера или возвращает его кешированную версию:

function getImage(imageUrl) {
    if (imageUrl in this.cache) {
        // no need to download, return immediately
        return Promise.resolve(this.cache[imageUrl]);
    } else {
        return new Promise(function(resolve, reject) {
            // start downloading and eventually resolve
        });
    }
}
person Sergey Rybalkin    schedule 08.09.2015
comment
Только для того, чтобы вызвать на нем then()? - person kraftwer1; 08.09.2015
comment
Да, это необходимо, если вызывающий код ожидает возврата обещания. Таким образом, вы не нарушите соглашение о вызовах, см. дополнительные примеры здесь - devdocs.io/javascript/global_objects /обещание/решение - person Sergey Rybalkin; 08.09.2015
comment
Использование уже разрешено вводит в заблуждение. Возвращенное обещание не должно быть уже разрешено, и обратный вызов then() для возвращенного обещания не обязательно будет вызываться очень скоро (в следующем цикле..) и может занять бесконечное количество времени в зависимости от того, что было опубликовано. в вызов resolve. - person Amit; 09.09.2015
comment
Я согласен с @Amit, я думаю, что создание обещания в случае, когда оно может уже решено, подходит лучше. Отличный пример, он иллюстрирует практический вариант использования. - person kraftwer1; 09.09.2015
comment
@Amit: На самом деле уже решено технически правильно. Однако это может быть еще не решено (а может быть, и никогда). - person Bergi; 09.09.2015
comment
@Bergi: var p = new Promise(() => {}), r = Promise.resolve(p); p === r и p / r (то же самое) не разрешены, на самом деле, console.log(r) показывает [[PromiseStatus]]: pending. Так что технически это может быть неразрешенным, но поскольку в примере разрешается значение (объект...), которое не является обещанием, оно будет разрешено. - person Amit; 09.09.2015
comment
@Amit: Ах, да, я забыл, что Promise.resolve может вернуть ввод. Тем не менее, это должно быть неотличимо от r = new Promise(res => res(p)) в поведении; и я бы сказал, что вы могли бы сказать, что r разрешается в p в обоих случаях. - person Bergi; 09.09.2015
comment
@Bergi - я бы сказал, что мы обсуждаем, насколько влажный океан - это не имеет никакого значения в реальном мире :-) - person Amit; 09.09.2015

Promise.resolve(42) — это просто сокращение для

new Promise(function(resolve) {
    resolve(42);
});

Поэтому всякий раз, когда вы обнаружите, что делаете что-то подобное, то есть создаете обещание из существующего значения, вы можете вместо этого использовать Promise.resolve.

person Felix Kling    schedule 08.09.2015

Семантически функции, возвращающие промисы, являются асинхронными функциями и, как вы знаете, могут быть объединены в цепочку:

a().then(b).then(c).catch(failure);

Хотя синхронные функции также могут быть частью асинхронных цепочек, это работает только потому, что функция .then автоматически переводит возвращаемые значения из функций, которые вы ей передаете, в промисы. Например. Если b и/или c возвращают значения, которые не являются промисами, то цепочка все еще работает, но если a возвращает не промис-значение, то это TypeError.

В большинстве случаев вы, вероятно, знаете, что возвращает a, так что это нормально, но в тех случаях, когда вы не знаете, что вернет a (скажем, вы занимаетесь универсальным программированием), вы можете сделать это:

Promise.resolve(a()).then(b).then(c).catch(failure);

a, b и c теперь обрабатываются одинаково в этом отношении:

  • Если a возвращает 1, то b скоро будет вызываться с 1.
  • Если a возвращает обещание, то b будет привязан к a.

Метод Promise.reject выполняет то же самое для цепочек отказов.

Кроме того, эти методы могут быть удобны в тех случаях, когда вам просто нужно обещание, которое разрешается сразу. Например.

[a, b, c].reduce((p, f) => p.then(f), Promise.resolve()).catch(failure);
person jib    schedule 09.09.2015
comment
Однако к ним не относятся одинаково, когда один из них бросает. Вместо этого вы можете использовать Promise.resolve().then(a)…. - person Bergi; 09.09.2015
comment
@Bergi хорошая мысль, спасибо за это. Эти два способа немного отличаются, поэтому обязательно выберите тот, который подходит именно вам. Если a действительно является первым методом в новой последовательности и у него есть синхронный компонент, то может быть желательно убедиться, что его синхронная часть запущена до возврата (большинство API-интерфейсов браузера, по крайней мере, стремятся выполнять проверку ввода синхронно, чтобы сделать их можно наблюдать в отладчике js, проверив состояние и причину обещания), или, может быть, просто чтобы избежать дополнительной отправки. Но если a, b и c истинно равны, то то, что вы предлагаете, может быть предпочтительнее. - person jib; 09.09.2015