2

我的机器人基于机器人框架并集成了许多渠道,主​​要是在电报中,我面临这个错误POST to botName timed out after 15s .. 代码中有什么方法可以限制代码吗?

4

1 回答 1

2

我遇到了类似的问题。我的机器人实际上并没有停止运行(老实说,我不确定是否会抛出 console.log 错误)但我确实Couldn't send. Retry在网络聊天 UI 中得到了。

此解决方案不能解决问题,但确实提供了一种解决方法。我希望如果其他人对这个问题有直接的解决方案,他们会分享它!不过,您可以做的是使 API 调用异步并通过主动消息发送响应。您可以明确地让用户知道(就像我在下面的示例中所做的那样),或者如果延迟不是那么长,您不必说什么。

需要 conversationReference 对象才能完成这项工作。我将我的机器人设置为在每个消息活动上生成它(因此,context.activity.type === ActivityTypes.Message如果您使用旧语法,则使用 onMessage 处理程序或 onTurn)。我将它保存为对话状态,以便我可以在整个机器人中访问它。您需要从 botbuilder 库中导入 TurnContext。保存对话参考很简单

// Save the conversationReference
const conversationData = await this.dialogState.get(context, {});
conversationData.conversationReference = TurnContext.getConversationReference(context.activity);
await this.conversationState.saveChanges(context);

我使用虚拟 API 整理了一个示例,如下所示。请注意,我不是在等待 API 调用。这就是阻止该Couldn't send. Retry消息出现的原因。如果您不需要或不想让用户知道会有延迟响应,您可以省略sendActivity。此外,您可以从您正在调用的其他函数访问对话状态,但是您必须以任何一种方式传递一些东西,看起来我只是传递了值而不是状态访问器。

case PROACTIVE_MSG_INTENT:
    await dc.context.sendActivity(`OK, I'll simulate a long-running API call and send a proactive message when it's done.`);
    const conversationData = await this.dialogState.get(context, {});
    apiSimulation.longRunningRequest(conversationData.conversationReference);
    break;

所以我这里的函数显然是一个模拟的API。你会在我有我的await new Promise(resolve => setTimeout(resolve, 30000));声明的地方调用你的 API。你确实想等待这个电话,因为你显然需要发回响应!但是您的机器人的其余部分将继续运行。这是我的整个示例函数。

const { BotFrameworkAdapter } = require('botbuilder');

class apiSimulation {
    static async longRunningRequest(conversationReference) {
        console.log('Starting simulated API');
        await new Promise(resolve => setTimeout(resolve, 30000));
        console.log('Simulated API complete');

        // Set up the adapter and send the message
        try {
            const adapter = new BotFrameworkAdapter({
                appId: process.env.microsoftAppID,
                appPassword: process.env.microsoftAppPassword,
                channelService: process.env.ChannelService,
                openIdMetadata: process.env.BotOpenIdMetadata
            });
            await adapter.continueConversation(conversationReference, async turnContext => {
                await turnContext.sendActivity('This message was sent after a simulated long-running API');
            });
        } catch (error) {
            console.log(error);
        }
    }
}

module.exports.apiSimulation = apiSimulation;

应该就是这样!您的机器人处理程序不会等待 API 响应,因此您不会收到消息,并且您的单独函数将等待响应并通过主动消息/continueConversation 发送。请注意,您不需要像在 GitHub 上的主动通知示例中那样为主动消息传递设置单独的端点。我想你可以从你的机器人中调用这个端点,但对我来说,创建一个新的适配器来继续对话似乎更有效。

于 2020-04-15T14:11:52.670 回答