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