Промисы (Promises)

Promise (обещание) — часть стандарта es6 и специальная функция (typeof Promise === 'function'), которую можно использовать для отложенных и асинхронных операций.

Многие современные стандарты и API имеют promise интерфейсы.

Синтаксис

const promise = new Promise(function(resolve, reject) { });

promise.then(result => { }, error => { });
// или
promise.then(result => {}).catch(error => {});

Описание

Для начала, давайте определимся что Promise может находиться в трёх состояниях:

  • ожидание (pending) — начальное состояние, не выполнено и не отклонено;
  • выполнено (fulfilled, resolved) — операция завершена успешно;
  • отклонено (rejected) — операция завершена с ошибкой.

Итак, при создании промис находится в ожидании (pending), затем он может стать выполненным (resolved) или отклонённым (rejected). В первом случае он может вернуть результат операции, а во втором ошибку (причину отказа). В любом из этих случаев вызовется прикреплённый обработчик then.

Примечания:

  • Промис может выполниться только один раз;
  • Промис не может поменят свой статус выполнения;
  • Промис нельзя отменить;
  • Выполнение обработчика then помещается в конец очереди main thread, примерно как setTimeout(..,0);
  • Обработчик then выполнится в любом случае, независимо от того был он прикреплён до или после того, как выполнился промис (resolved или rejected).

Цепочки

Обработчик then (как и catch) возвращает промис, соответственно мы можем организовать цепочку операций (синхронных или асинхронных), например для последовательной обработки данных.

promise.then(result1 => {
    // возвращаем изменённые данные
}).then(result2 => {
    // или новый промис
});

Если возвращать значение, оно автоматически завернётся в resolved промис, и следующий then будет вызван с этим значением. Если же возвращать промис, то следующий then дождётся выполнения этого промиса, и только потом будет вызван.

Последовательное выполнение

Следующий пример показывает как можно использовать динамические цепочки в циклах:

chapterUrls.reduce((sequence, chapterUrl) => {
    return sequence.then(function() {
        return getJSON(chapterUrl);
    }).then(function(chapter) {
        addHtmlToPage(chapter.html);
    });
}, Promise.resolve());

Promise.resolve() — выполненный промис, и начало нашей цепочки.

Параллельное выполнение

Некоторые операции браузер может делать параллельно, например загрузку ресурсов. С помощью промисов мы можем легко выполнить некоторый код после загрузки всех необходимых ресурсов:

// arrayOfPromises = массив промисов.
// один промис = загрузка одного ресурса.
Promise.all(arrayOfPromises)
    .then(function(arrayOfResults) {
        // arrayOfResults = массив возвращенных промисами значений 
        // в том же порядке, в котором вы их передали.
    });

Ссылки

results matching ""

    No results matching ""