JavaScript Promise.try()

JavaScript Tutorials


JavaScript Promise.try() runs a callback and wraps its outcome in a Promise. The callback may return a normal value, throw an error, or return another Promise. Your following .then() and .catch() handlers can process all three cases through one consistent chain.

This method is useful when your code calls a function whose behavior is not fully predictable. A plugin, configuration reader, validation rule, or user callback may work synchronously today and return a Promise later.

Promise.try() Syntax

Pass the function itself as the first argument. You may provide additional arguments after it; Promise.try() forwards them to the callback.

Syntax:

Promise.try(callback)
Promise.try(callback, argument1, argument2)
Callback outcome Resulting Promise
Returns a normal value Fulfilled with that value
Throws an error Rejected with that error
Returns a fulfilled Promise Fulfilled with its final value
Returns a rejected Promise Rejected with the same reason

Handle a Value or a Thrown Error

The following function parses stored JSON. A valid string returns an object, while malformed JSON throws a SyntaxError. Promise.try() turns the thrown error into a rejection.

Example:

// This callback can return an object or throw before returning.
function readProfile() {
  const profile = '{"name":"Ava","points":42}';
  return JSON.parse(profile);
}

Promise.try(readProfile)
  .then(user => console.log(user.name, user.points))
  .catch(error => console.error(error.message));

Output:

Ava 42

Use the Run Code button to execute a browser example. Change the JSON string so it is invalid and the same chain will display the parsing error.

Why Promise.resolve(callback()) Is Different

This expression looks similar, but JavaScript must call callback() before it can pass the result to Promise.resolve(). If that call throws, no Promise is created and a later .catch() cannot receive the error.

// A synchronous throw escapes before Promise.resolve() runs.
Promise.resolve(callback()).catch(handleError);

Passing the callback to Promise.try() gives the method control of the call, so it can translate a synchronous throw into a rejected Promise.

// Promise.try() catches a synchronous throw as a rejection.
Promise.try(callback).catch(handleError);

Work with Synchronous and Asynchronous Functions

A single helper can call functions that use either style. The consumer does not need to test the returned value with instanceof Promise.

Example:

function getLocalRate(currency) {
  // A synchronous source returns immediately.
  if (currency === "INR") return 83.25;

  // A remote source returns a Promise.
  return fetch("/api/rates/" + currency)
    .then(response => {
      if (!response.ok) throw new Error("Rate unavailable");
      return response.json();
    })
    .then(data => data.rate);
}

Promise.try(getLocalRate, "INR")
  .then(rate => console.log("Rate:", rate))
  .catch(error => console.error(error.message));

Output:

Rate: 83.25

Pass Arguments Without an Extra Wrapper

Additional arguments avoid creating a new arrow function only to call the target function. This also keeps the original callback and its arguments separate.

Example:

function calculateTotal(price, quantity) {
  // Reject invalid input with a normal synchronous error.
  if (quantity < 1) throw new RangeError("Quantity must be positive");
  return price * quantity;
}

Promise.try(calculateTotal, 799, 2)
  .then(total => console.log("Total:", total))
  .catch(error => console.error(error.message));

Output:

Total: 1598

Execution Timing

Promise.try() invokes its callback synchronously. Promise reaction handlers still run asynchronously in the microtask queue. This distinction matters when the callback changes shared state.

console.log("Before");

Promise.try(() => {
  console.log("Callback"); // Runs during the current call
  return "Done";
}).then(console.log);       // Runs in a microtask

console.log("After");

Output:

Before
Callback
After
Done

Fallback for Older Environments

Current browsers support Promise.try(), but older environments may not. Use feature detection when your supported browser list includes them.

// Preserve the same value, error, and Promise handling behavior.
const tryPromise = Promise.try ?? ((callback, ...args) =>
  new Promise((resolve, reject) => {
    try {
      resolve(callback(...args));
    } catch (error) {
      reject(error);
    }
  })
);

Best Practices

  • Pass the callback instead of calling it before Promise.try().
  • Use normal Promise error handling after the call.
  • Do not use it merely to wrap a value; Promise.resolve(value) is clearer for that case.
  • Keep callback side effects clear because the callback begins synchronously.
  • Check your runtime support before removing a fallback.

Conclusion

Promise.try() provides one entry point for callbacks that may return values, throw errors, or return promises. Use it at uncertain synchronous-asynchronous boundaries to simplify control flow while preserving standard Promise handling.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram