Spec-Zone.ru › JavaScript

Promise.try()

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

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

Статический метод Promise.try() принимает функцию обратного вызова любого типа (возвращает или выбрасывает, синхронно или асинхронно) и разрешает ее результат в Promise.

Синтаксис

Promise.try(func)
Promise.try(func, arg1)
Promise.try(func, arg1, arg2)
Promise.try(func, arg1, arg2, /* …, */ argN)

Параметры

func
Функция, которая вызывается синхронно с предоставленными аргументами (arg1, arg2, …, argN). Она может делать что угодно — возвращать значение, выбрасывать ошибку или возвращать промис.
arg1, arg2, …, argN
Аргументы для передачи в func.

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

Promise, который:

  • Уже выполнен, если func синхронно возвращает значение.
  • Уже отклонен, если func синхронно выбрасывает ошибку.
  • Асинхронно выполнен или отклонен, если func возвращает промис. Возвращаемое значение разрешается в промис, что означает, что встроенные объекты Promise возвращаются как есть.

Описание

У вас может быть API, который принимает функцию обратного вызова. Функция обратного вызова может быть синхронной или асинхронной. Вы хотите обрабатывать все единообразно, обернув результат в промис. Самый простой способ — это Promise.resolve(func()). Проблема в том, что если func() синхронно выбрасывает ошибку, эта ошибка не будет перехвачена и превращена в отклоненный промис.

Вы можете обернуть это выражение в try...catch:

let result;
try {
  result = Promise.resolve(func());
} catch (error) {
  result = Promise.reject(error);
}

Проблема в том, что try...catch не является выражением, поэтому вы не можете использовать его напрямую в позициях выражений, таких как передача его другим функциям.

Поэтому, при переносе результата вызова функции в промис, выполненный или отклоненный, люди чаще делают так:

new Promise((resolve) => resolve(func()));

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

Promise.try() почти точно эквивалентен подходу с try...catch, за исключением того, что он короче и может использоваться как выражение:

Promise.try(func);

Примечание: Promise.try() изначально был указан и реализован для работы, как версия new Promise(), безоговорочно создавая новый промис, но теперь это не так. См. совместимость с браузерами.

Обратите внимание, что Promise.try() *не* эквивалентен этому, несмотря на то, что он очень похож:

Promise.resolve().then(func);

Разница в том, что функция обратного вызова, переданная в then(), всегда вызывается асинхронно, в то время как исполнитель конструктора Promise() вызывается синхронно. Promise.try также вызывает функцию синхронно и немедленно разрешает промис, если это возможно.

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

Подобно setTimeout(), Promise.try() принимает дополнительные аргументы, которые передаются в функцию обратного вызова. Это означает, что вместо:

Promise.try(() => func(arg1, arg2));

Вы можете сделать:

Promise.try(func, arg1, arg2);

Что эквивалентно, но последнее избегает создания дополнительной замыкающей области и более эффективно.

Promise.try() является общим и поддерживает наследование, что означает, что его можно вызывать для подклассов Promise, и результат будет содержать промис типа подкласса. Для этого конструктор подкласса должен реализовать тот же сигнатуру, что и конструктор Promise() — принимая одну функцию executor, которая может быть вызвана с параметрами resolve и reject.

Примеры

Использование Promise.try()

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

function doSomething(action) {
  return Promise.try(action)
    .then((result) => console.log(result))
    .catch((error) => console.error(error))
    .finally(() => console.log("Done"));
}

doSomething(() => "Sync result");

doSomething(() => {
  throw new Error("Sync error");
});

doSomething(async () => "Async result");

doSomething(async () => {
  throw new Error("Async error");
});

В async/await тот же код будет выглядеть так:

async function doSomething(action) {
  try {
    const result = await action();
    console.log(result);
  } catch (error) {
    console.error(error);
  } finally {
    console.log("Done");
  }
}

Вызов try() на конструкторе, не являющемся Promise

Promise.try() — это общий метод. Его можно вызывать для любого конструктора, который реализует ту же сигнатуру, что и конструктор Promise().

Следующее является несколько более точным приближением реального Promise.try() (хотя его все равно не следует использовать в качестве полифилла):

Promise.try = function (func, ...args) {
  let result;
  try {
    result = func(...args);
  } catch (error) {
    return Promise.reject.call(this, error);
  }
  return Promise.resolve.call(this, result);
};

Promise.try() делегирует Promise.resolve() и Promise.reject() для создания возвращаемого значения, и обе эти функции являются общими.

Например, мы можем вызвать его для конструктора, который передает console.log в качестве функций resolve и reject в executor:

class NotPromise {
  constructor(executor) {
    // The "resolve" and "reject" functions behave nothing like the native
    // promise's, but Promise.try() just calls resolve
    executor(
      (value) => console.log("Resolved", value),
      (reason) => console.log("Rejected", reason),
    );
  }

  static try = Promise.try;
}

const p = NotPromise.try(() => "hello");
// Logs: Resolved hello
// p is a NotPromise instance

const p2 = NotPromise.try(() => {
  throw new Error("oops");
});
// Logs: Rejected Error: oops
// p2 is a NotPromise instance

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

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

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

Настольные компьютеры Мобильные устройства Сервер
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
try
128
128
134
114
18.2
128
134
85
18.2
28.0
128
18.2
1.1.22
1.46
23.0.0

См. также

  • Полифилл для Promise.try в core-js
  • Полифилл es-shims для Promise.try
  • Руководство по использованию промисов
  • Promise
  • Конструктор Promise()

© 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/try

Spec-Zone.ru

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