Spec-Zone.ru › JavaScript

Promise.prototype.finally()

Базовый уровень Широко доступно

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с октября 2018 года.

Метод finally() экземпляров Promise планирует вызов функции, когда промис завершен (либо выполнен, либо отклонен). Он немедленно возвращает другой объект Promise, позволяя вам связывать вызовы других методов промисов в цепочку.

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

Попробуйте

function checkMail() {
  return new Promise((resolve, reject) => {
    if (Math.random() > 0.5) {
      resolve("Mail has arrived");
    } else {
      reject(new Error("Failed to arrive"));
    }
  });
}

checkMail()
  .then((mail) => {
    console.log(mail);
  })
  .catch((err) => {
    console.error(err);
  })
  .finally(() => {
    console.log("Experiment completed");
  });

Синтаксис

promiseInstance.finally(onFinally)

Параметры

onFinally
Функция для асинхронного выполнения, когда этот промис завершен. Если функция возвращает промис, результирующий промис будет ожидать завершения этого промиса, прежде чем продолжить. Если возвращенный промис отклонен, результирующий промис отклоняется по той же причине. Любое другое возвращаемое значение или выполненное значение возвращенного промиса игнорируется.

Возвращаемое значение

Немедленно возвращает новый Promise. Этот новый промис всегда находится в состоянии ожидания (pending) при возврате, независимо от статуса текущего промиса. Если onFinally вызывает ошибку или возвращает отклоненный промис, новый промис будет отклонен с этим значением. В противном случае новый промис завершится тем же состоянием, что и текущий промис.

Описание

Метод finally() может быть полезен, если вы хотите выполнить некоторую обработку или очистку после завершения промиса, независимо от его результата.

Метод finally() очень похож на вызов then(onFinally, onFinally). Однако есть пара отличий:

  • При создании функции прямо в строке вы можете передать ее один раз, вместо того чтобы быть вынужденным объявлять ее дважды или создавать для нее переменную.
  • Коллбэк onFinally не принимает никаких аргументов. Этот вариант использования предназначен именно для тех случаев, когда вас не интересует причина отклонения или значение выполнения, и, следовательно, нет необходимости их предоставлять.
  • Вызов finally() обычно прозрачен и отражает конечное состояние исходного промиса. Например:
    • В отличие от Promise.resolve(2).then(() => 77, () => 77), который возвращает промис, в конечном итоге выполненный со значением 77, Promise.resolve(2).finally(() => 77) возвращает промис, в конечном итоге выполненный со значением 2.
    • Аналогично, в отличие от Promise.reject(3).then(() => 88, () => 88), который возвращает промис, в конечном итоге выполненный со значением 88, Promise.reject(3).finally(() => 88) возвращает промис, в конечном итоге отклоненный с причиной 3.

Примечание: throw (или возврат отклоненного промиса) в колбэке finally все равно отклоняет возвращенный промис. Например, оба Promise.reject(3).finally(() => { throw 99; }) и Promise.reject(3).finally(() => Promise.reject(99)) отклоняют возвращенный промис с причиной 99.

Подобно catch(), finally() внутренне вызывает метод then на объекте, на котором он был вызван. Если onFinally не является функцией, then() вызывается с onFinally в качестве обоих аргументов, что для Promise.prototype.then() означает, что полезный обработчик не прикреплен. В противном случае then() вызывается с двумя внутренне созданными функциями, которые ведут себя следующим образом:

Предупреждение: Это предназначено только для демонстрационных целей и не является полифилом.

promise.then(
  (value) => Promise.resolve(onFinally()).then(() => value),
  (reason) =>
    Promise.resolve(onFinally()).then(() => {
      throw reason;
    }),
);

Поскольку finally() вызывает then(), он поддерживает наследование (subclassing). Кроме того, обратите внимание на вызов Promise.resolve() выше — на самом деле, возвращаемое значение onFinally() разрешается с использованием того же алгоритма, что и Promise.resolve(), но фактическим конструктором, используемым для создания разрешенного промиса, будет подкласс. finally() получает этот конструктор через promise.constructor[Symbol.species].

Примеры

Использование finally()

let isLoading = true;

fetch(myRequest)
  .then((response) => {
    const contentType = response.headers.get("content-type");
    if (contentType && contentType.includes("application/json")) {
      return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
  })
  .then((json) => {
    /* process your JSON further */
  })
  .catch((error) => {
    console.error(error); // this line can also throw, e.g. when console = {}
  })
  .finally(() => {
    isLoading = false;
  });

Спецификации

Спецификация
ECMAScript® 2027 Language Specification
# sec-promise.prototype.finally

Совместимость с браузерами

Настольные Мобильные Серверные
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
finally
63
18
58
50
11.1
63
58
46
11.3
8.0
63
11.3
1.0.0
1.0
10.0.0

Смотрите также

  • Полифил Promise.prototype.finally в core-js
  • es-shims полифил Promise.prototype.finally
  • Promise
  • Promise.prototype.then()
  • Promise.prototype.catch()

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API