> Как создать собственную функцию executor в Promise в JavaScript (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Яндекс
Стек: JavaScript
> Пример ответа
Короткий ответ
Собственная функция executor в Promise - это функция, передаваемая в конструктор new Promise(executor). Она принимает два параметра: resolve и reject, которые являются функциями обратного вызова. Вызов resolve(value) переводит promise в состояние fulfilled, а reject(reason) - в rejected. Executor выполняется синхронно при создании promise, до того как будет возвращён сам promise-объект.
Подробное объяснение
Executor - это сердце любого Promise. Он предоставляет механизм управления асинхронной операцией. Когда вы пишете new Promise((resolve, reject) => { ... }), эта стрелочная функция и есть executor. Важно понимать, что executor выполняется немедленно и синхронно в момент вызова конструктора Promise. Это означает, что любой код внутри executor, не являющийся асинхронным, выполняется до того, как promise будет возвращён.
Executor может вызывать resolve или reject только один раз - последующие вызовы игнорируются. Если executor выбрасывает синхронное исключение, promise автоматически переходит в состояние rejected с этим исключением. Это поведение отличает executor от обычных функций - ошибка не всплывает, а перехватывается конструктором Promise.
Executor не может возвращать значение напрямую - его результат игнорируется. Вся коммуникация происходит через resolve и reject. Это позволяет инкапсулировать асинхронную логику и предоставить единый интерфейс для обработки результата.
На практике
При создании собственного executor вы должны явно вызывать resolve или reject в нужный момент. Типичный сценарий - обёртка callback-based API, например, setTimeout, fs.readFile или XMLHttpRequest. Важно гарантировать, что вызов resolve или reject произойдёт ровно один раз, иначе promise зависнет в состоянии pending.
Executor может быть асинхронным сам по себе - вы можете использовать внутри него async/await, но это не меняет его синхронного выполнения. Если executor помечен как async, он вернёт promise, но конструктор Promise этого не ожидает - он просто игнорирует возвращаемое значение. Исключение из асинхронного executor не будет автоматически преобразовано в reject, поэтому нужно явно обрабатывать ошибки.
Пример кода
JAVASCRIPT// Собственный executor для setTimeoutfunction delay(ms) {return new Promise((resolve) => {setTimeout(() => {resolve(`Прошло ${ms} мс`);}, ms);});}// Executor с обработкой ошибокfunction fetchData(url) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.open('GET', url);xhr.onload = () => {if (xhr.status >= 200 && xhr.status < 300) {resolve(xhr.responseText);} else {reject(new Error(`HTTP ${xhr.status}`));}};xhr.onerror = () => reject(new Error('Network error'));xhr.send();});}// Executor с синхронным исключениемconst safePromise = new Promise((resolve, reject) => {throw new Error('Синхронная ошибка');// Promise автоматически станет rejected});
Как отвечать на собеседовании
Начните с определения executor и его сигнатуры. Подчеркните, что executor выполняется синхронно - это ключевой момент, который часто упускают. Объясните, что resolve и reject - это функции, предоставляемые конструктором Promise, и их можно вызывать только один раз. Приведите пример обёртки callback-based API. Упомяните, что executor не должен быть async-функцией, если вы ожидаете автоматического перехвата ошибок. Завершите тем, что executor - это паттерн для преобразования асинхронных операций в promise-based интерфейс.
Что проверяет интервьюер
Интервьюер оценивает понимание внутреннего устройства Promise: синхронность executor, однократность вызова resolve/reject, обработка исключений. Также проверяется способность применить эти знания на практике - обёртка legacy API, работа с асинхронными операциями. Важно показать, что вы понимаете разницу между executor и обычной функцией, особенно в контексте ошибок и асинхронности.
Типичные ошибки
- Вызов
resolveилиrejectнесколько раз - последующие вызовы игнорируются, но это может сбить с толку. - Использование async-функции в качестве executor без явной обработки ошибок - исключения не будут автоматически превращены в reject.
- Забывание вызвать
resolveилиreject- promise остаётся в состоянии pending навсегда. - Попытка вернуть значение из executor - оно игнорируется, нужно использовать
resolve. - Путаница между executor и обработчиками
.then()- executor выполняется сразу, а не при разрешении promise.
> Похожие задачи по frontend
Какой тип данных должна возвращать функция retry в JavaScript
Почему нельзя использовать Map вместо объекта для возвращаемого значения метода groupBy в JavaScript
Как обрабатывать JSON ответ в JavaScript
Как реализовать кэш с методами get, set, delete и clear с поддержкой TTL в JavaScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью