Соревнуйте Promise исходной операции с Promise таймера и очищайте таймер в finally. Это ограничивает ожидание результата, но само по себе не прекращает выполняющуюся задачу.
Ограничитель времени выполнения для асинхронных функций
Соревнуйте Promise исходной операции с Promise таймера и очищайте таймер в finally. Это ограничивает ожидание результата, но само по себе не прекращает выполняющуюся задачу.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо реализовать функцию‑обёртку, принимающую два параметра – асинхронную функцию и лимит времени в миллисекундах. Возвращаемая функция должна выполнять исходную асинхронную задачу, но не дольше указанного ограничения. Требования: • Если работа исходной функции завершается быстрее лимита, обёртка должна вернуть полученный результат. • Если выполнение превышает заданный предел, обёртка должна отклонить промис с сообщением «Превышен лимит времени исполнения».
const originalFn = async (n) => {
await new Promise(res => setTimeout(res, 100));
return n * n;
}
withTimeout(originalFn, 50)(5); // rejected: Превышен лимит времени исполнения
withTimeout(originalFn, 150)(5); // resolved: 25
const sumFn = async (a, b) => {
await new Promise(res => setTimeout(res, 120));
return a + b;
}
withTimeout(sumFn, 100)(1, 2); // rejected: Превышен лимит времени исполнения
withTimeout(sumFn, 150)(1, 2); // resolved: 3
Ответ
Соревнуйте Promise исходной операции с Promise таймера и очищайте таймер в finally. Это ограничивает ожидание результата, но само по себе не прекращает выполняющуюся задачу.
function withTimeout(fn, ms) {
return async function (...args) {
let timer;
const timeout = new Promise((_, reject) => {
timer = setTimeout(() => reject(new Error('Превышен лимит времени исполнения')), ms);
});
try {
const work = Promise.resolve().then(() => fn.apply(this, args));
return await Promise.race([work, timeout]);
} finally { clearTimeout(timer); }
};
}
Предполагается конечный неотрицательный ms. Аргументы, this и успешное значение сохраняются; синхронное исключение fn тоже превращается в rejection. Для фактической отмены запрос должен принимать AbortSignal или другой механизм остановки. Долгий синхронный код блокирует даже таймер, поэтому такая обёртка не является прерывателем CPU-работы.