JavaScript Promise.withResolvers: вынести resolve

Категория: JavaScript · Язык: JavaScript · Обновлено:

Promise.withResolvers() возвращает объект с самим промисом и функциями resolve и reject. Метод появился в ES2024 и убирает обходной путь с let resolve; new Promise((r) => { resolve = r; }). Он полезен, когда решение о завершении принимает внешний callback, событие или другая функция.

Создать промис и завершить его позже

JavaScript
const {promise, resolve} = Promise.withResolvers();

setTimeout(() => resolve("готово"), 10);

console.log(await promise); // готово

Функции resolve и reject можно вызывать где угодно: в обработчике события, таймере или другом модуле. Промис завершится только один раз; повторный вызов resolve или reject игнорируется. Если вызвать reject, а обработчик ошибки не добавить, возникнет unhandledRejection, поэтому возвращайте промис вызывающему коду или сразу добавляйте catch.

Типичный сценарий — обернуть API с callback:

JavaScript
function readValue(file, reader) {
    const {promise, resolve, reject} = Promise.withResolvers();

    reader.onload = () => resolve(reader.result);
    reader.onerror = () => reject(reader.error);

    reader.readAsText(file);
    return promise;
}

В примере с FileReader функции сохраняются в замыкании и вызываются асинхронно. Без withResolvers пришлось бы объявлять переменные заранее и следить, чтобы reject не остался undefined.

Метод поддерживается в Chrome 119+, Firefox 121+, Safari 17.4+ и Node.js 22+. В старых окружениях нужен полифил или обычный new Promise. Не используйте withResolvers для синхронной проверки условий: если ошибка известна сразу, проще выбросить исключение или вернуть Promise.reject(). И не храните resolve в глобальной области: это затрудняет отслеживание завершения промиса.

Документация: Promise.withResolvers, ECMAScript 2024.