Node.js 和 Telegraf TimeoutError: Promise 在 90000 毫秒后超时

Posted

技术标签:

【中文标题】Node.js 和 Telegraf TimeoutError: Promise 在 90000 毫秒后超时【英文标题】:Node.js and Telegraf TimeoutError: Promise timed out after 90000 milliseconds 【发布时间】:2021-10-16 05:08:45 【问题描述】:

我有一个函数可以处理来自某个用户的一些披萨订单。我把它分为两部分:从用户那里获取数据和填充输入、点击按钮等。

const handleUserOrder = async (page, $, ctx) => 
    const name, size, sauce = await getUserOrder($, ctx)

    //absolutely unimportant and useless code for my issue goes below

错误出现在我的函数的第一部分,即获取数据:

const getUserOrder = async ($, ctx) => 
    let titles = []
    $('.goods__list__title').slice(0, 30).each((index, element) => 
        const title = $(element).text().trim()
        titles.push(title)
    )
    await ctx.reply(`Ну ладно, держи список: \n\n$titles.map(title => title + ' (' + (titles.indexOf(title) + 1) + ')').join('\n')`)
    await keyboard.sendMessage(ctx.from.id, 'Напиши номер той пиццы, которую ты выбрал.')

    const name = await getName(titles)
    await keyboard.sendMessage(ctx.chat.id, `Значит $name. Размер?`)
    const size = await getSize(ctx)
    await keyboard.sendMessage(ctx.chat.id, `Так, с размером определились. Может теперь выберешь соус?`)
    await keyboard.sendMessage(ctx.chat.id, 'Одну секунду...')
    const sauce, order = await getSauce(ctx)
    await keyboard.sendMessage(ctx.chat.id, `Вот твой заказ: $order.`)
    return name, size, sauce

如您所见,我为需要收集的每条数据创建了三个函数。而这就是发生错误的地方。

const getName = async (titles) => 
    const options = await titles.map(title => `$titles.indexOf(title) + 1`)
    await ctx.reply('Выбирай любую!', 
        reply_markup: 
            keyboard: new Array(titles.length).fill(0).map((e, i) => [text: `$i + 1`]),
            resize_keyboard: true,
            one_time_keyboard: true,
            remove_keyboard: true,
        
    )
    await bot.hears(options, async (ctx) => 
        return titles[parseInt(ctx.match[0]) - 1]
    )

我已经认识到只有当return 方法位于嵌套的最后一层时才会出现此错误。否则,例如,如果我只给name 一些特定的值,而不是选择它作为用户,它绝对可以正常工作,因为根本没有嵌套。

您对如何解决它有任何想法吗?

这是我的代码在 Promise 下的样子(@ggorlen 的建议):

const getName = async (titles, ctx) => 
    const options = await titles.map(title => `$titles.indexOf(title) + 1`)
    await ctx.reply('Выбирай любую!', 
        reply_markup: 
            keyboard: new Array(titles.length).fill(0).map((e, i) => [text: `$i +1`]),
            resize_keyboard: true,
            one_time_keyboard: true,
            remove_keyboard: true,
        
    )

    return new Promise(res => 
        bot.hears(options, ctx => 
            res(titles[parseInt(ctx.match[0]) - 1])
        )
    )

现在在调用函数之后经过一段时间后,我得到了这个错误:

(node:20076) UnhandledPromiseRejectionWarning: TimeoutError: Promise timed out after 90000 milliseconds
    at Timeout._onTimeout (/Users/mishashkarubski/WebstormProjects/pizza/node_modules/p-timeout/index.js:39:64)
    at listOnTimeout (internal/timers.js:557:17)
    at processTimers (internal/timers.js:500:7)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:20076) UnhandledPromiseRejectionWarning: Unhandled promise rejection. 

This error originated either by throwing inside of an async function without a catch block,
or by rejecting a promise which was not handled with .catch().

To terminate the node process on unhandled promise rejection,
use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

(node:20076) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated.
In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

【问题讨论】:

您的return titles[...] 不会像您想象的那样返回给getName 的调用者——它返回可能会忽略结果的bot.hears API。 bot.hears 回调中的 async 毫无意义。您将需要 return new Promise(res => bot.hears( ... res(titles[...]))) 或找到基于承诺的 API 而不是回调。 @ggorlen 我试图返回一个 Promise 而不是 return titles[...] 但现在当我试图让我的机器人听到我输入的内容时我没有得到任何结果 (bot.hears API根本不起作用) 这对我来说一目了然——我没有电报,所以我无法真正测试它,但我会尝试添加一些日志以查看正在运行的内容。 @Mike'Pomax'Kamermans 我在我的问题中添加了一条错误消息。也许您对如何解决它有任何想法? 至于报错:告诉你,在 promise 中等待响应 90 秒后,Node 放弃了。所以,开始调试吧:在你的多个await 之间抛出一些console.log 语句,看看哪个停止了,然后从那里开始调查。 (await blah 只是使用 Promises 的替代语法,x = await y 等同于 y.then(x => ...) 【参考方案1】:

你试过这样吗?

const getName = async (titles) => 
    const options = await titles.map(title => `$titles.indexOf(title) + 1`)
    
    await bot.hears(options, async (ctx) => 
await ctx.reply('Выбирай любую!', 
        reply_markup: 
            keyboard: new Array(titles.length).fill(0).map((e, i) => [text: `$i + 1`]),
            resize_keyboard: true,
            one_time_keyboard: true,
            remove_keyboard: true,
        
    )
        return titles[parseInt(ctx.match[0]) - 1]
    )

【讨论】:

以上是关于Node.js 和 Telegraf TimeoutError: Promise 在 90000 毫秒后超时的主要内容,如果未能解决你的问题,请参考以下文章

[转帖]使用Grafana和Telegraf监视VMware ESXi的方法

TICK技术栈Telegraf安装及使用

数据实时监控平台:Telegraf简介及安装

Telegraf部署

telegraf连接influxdb提示:connection refused

如何使用 telegraf 监控远程系统指标?