Не так давно я читал блог Бена Илегбоду, и он рассказал, как расширить API выборки, чтобы пользователь мог установить тайм-аут. Это отличное чтение, и я очень рекомендую его. Я подумал, что было бы здорово перефразировать этот пост и сделать еще пару шагов вперед.

Во-первых, я хотел сделать его еще более универсальным, обернув любую функцию, возвращающую обещание, а не только Fetch API. Во-вторых, я хотел сделать это на TypeScript. В этом посте я планирую первую цель, а затем мы конвертируем его в TypeScript в будущем посте.

Окончательный код

Прежде чем мы углубимся в детали, вот конечный продукт:

Вспомогательная функция ожидания

Во-первых, мы сделали вспомогательную функцию под названием wait. Бен подробно описывает эту вспомогательную функцию, поэтому я подытожу. Функция wait требует времени ожидания в миллисекундах. Затем он возвращает обещание, которое будет разрешено по истечении времени в миллисекундах. Мы рассмотрим, почему это важно, через мгновение.

Функция withTimout

Затем мы определяем функцию withTimeout,, которая принимает два аргумента. Во-первых, он принимает функцию, которая возвращает Promise. Неважно, что делает функция, главное, чтобы она возвращала Promise. Во-вторых, он принимает объект конфигурации параметров. Этот объект используется для настройки как продолжительности тайм-аута, так и сообщения об ошибке, если это произойдет.

Собственно, именно это мы и делаем в следующих двух строках. Мы используем необязательное связывание и нулевые операторы объединения, чтобы либо использовать тайм-аут и сообщение об ошибке, предоставленные в объекте параметров, либо разумные значения по умолчанию.

Вернуть нашу обернутую функцию

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

К счастью, мы можем воспользоваться остальными и расширенными операторами. Мы используем оператор rest, чтобы упаковать все аргументы, переданные в массив, и присвоить их оттуда args, затем мы можем распространить все значения из args в переданную функцию обещания.

Мы не просто вызываем функцию обещания сама по себе. Какой в ​​этом смысл? Вместо этого мы вызываем внутри метода Promise.race. Promise.race принимает массив промисов. Первое, что нужно разрешить или отклонить, — это то, что будет возвращено методом.

Вот тут-то и появляется наша вспомогательная функция wait. Мы вызываем ее с нашим значением тайм-аута. Если он разрешится до нашей функции обещания, он выдаст ошибку. В противном случае функция обещания разрешится, а функция wait будет проигнорирована.

Вот оно. У нас есть функция, которая берет любую функцию на основе обещаний и возвращает новую идентичную функцию, которая выдает ошибку, если истекает время ожидания. В следующем посте мы рассмотрим, как использовать дженерики для добавления типов в вашу функцию withTimout.