Как исправить общую функцию, которая обрабатывает асинхронные функции

Я хочу создать общую функцию, которая принимает асинхронную функцию, выполняет ее и перехватывает ошибку, если предоставленная функция сталкивается с какими-либо проблемами.

так как я пришел из фона javascript, я смог создать следующую функцию, которая делает именно это. но я хотел улучшить его с помощью дженериков и не смог этого сделать

этот код работает так, как ожидалось. но я не получаю никакого типа в своем аргументе «msg».

const botAsyncHandler = (fn:Function) => (msg: any) => {
  Promise.resolve(fn(msg)).catch(error => {
    console.info(error.message);
  });
};

поэтому я попытался написать следующее

const botAsyncHandler = <T extends any>(fn:Function)=> (msg: T) => {
  Promise.resolve(fn(msg)).catch(error => {
    console.info(error.message);
    console.info('here');
  });
};

к сожалению, мой код не работает, и IDE по-прежнему сообщает мне, что msg имеет тип any неявно в следующем коде

bot.on('photo', botAsyncHandler(async msg => {}))

(возвращает: Parameter 'msg' implicitly has an 'any' type.)

но выделение botAsyncHandler показывает следующее:

botAsyncHandler<TelegramBot.Message>(fn: Function): (msg: TelegramBot.Message) => void

Что похоже на то, что я хочу. Мне любопытно знать, где я ошибаюсь

Дополнительное замечание о вашей реализации JavaScript: если вы знаете, что fn — это async, то нет смысла Promise.resolve(fn(arg)). Если вы не знаете, что fn является async (например, это может быть, а может и не быть), вы не будете отлавливать ошибки таким образом, если он синхронный.

T.J. Crowder 07.04.2019 18:00

@T.J.Crowder, вся цель функции - поймать отказ от обещания и обработать его. Это всегда асинхронно. Promise.resolve(fn(arg)) был просто для согласованности. функция не должна ничего возвращать. такой пустой

Omid 07.04.2019 18:06

Согласованность с какие?

T.J. Crowder 07.04.2019 18:06

@T.J.Crowder хороший момент. когда я это писал, функция всегда должна была возвращать обещание, и я хотел, чтобы код был понятным.

Omid 07.04.2019 18:11
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
1
4
1 342
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Из вашего примера использования:

bot.on('photo', botAsyncHandler(async msg => {}))

и пример JavaScript, похоже, вы пытаетесь создать функцию, которая будет возвращать функцию, которая при вызове будет вызывать оригинал, но обрабатывать ошибки из него. Самый простой способ сделать это — просто написать функцию async с try/catch в ней. Версия JavaScript:

const botAsyncHandler = (fn) => async (msg) => {
  try {
    await fn(msg);
  } catch (error) {
    console.info(error.message);
  }
};

добавление к нему аннотаций типа с обобщениями:

type AsyncHandler<T> = (arg: T) => {};
const botAsyncHandler = <T extends any>(fn: AsyncHandler<T>) => async (msg: T) => {
  try {
    await fn(msg);
  } catch (error) {
    console.info(error.message);
  }
};

Это предполагает, что функция должна объявить один формальный параметр. Жить на детской площадке.

Но я не уверен, что добавление параметра типа даст вам что-то здесь, учитывая, что вы используете <T extends any>.

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

Omid 07.04.2019 19:20

@Омид - Действительно. Если бы это был я, я бы просто предложил изменения, но...

T.J. Crowder 07.04.2019 19:22
Ответ принят как подходящий

Тип Function бесполезен. Не используйте его. Тип параметра fn примерно такой: (msg: T) => Promise<void>. Или вы можете принять синхронные функции, которые возвращают void: (msg: T) => void | Promise<void>.

Вы можете написать:

const botAsyncHandler = <T>(fn: (msg: T) => void | Promise<void>) => async (msg: T) => {
    try {
        await fn(msg);
    } catch (err) {
        console.info(err.message);
    }
};

const onString = (msg: string) => {};
const fn = botAsyncHandler(onString);
// Here, the type of 'fn' is: '(msg: string) => Promise<void>'

И я не могу проверить, но ваш код должен работать так, как ожидалось:

bot.on('photo', botAsyncHandler(async msg => {}))

Другие вопросы по теме