管理长期 运行 操作 node.js

Manage a long-running operation node.js

我正在创建一个电报机器人,它允许您使用 Bungie API 获取有关命运 2 游戏世界的一些信息。该机器人基于 Bot Framework 并使用 Telegram 作为渠道(作为我正在使用的语言 JavaScript)。

现在我发现自己处于这样一种情况:当我向机器人发送请求时,它使用一系列对 API 端点的 HTTP 调用来收集信息、格式化信息并通过自适应卡片重新提交信息,但是在许多情况下,这个过程需要超过 15 秒,在聊天中显示消息“POST to DestinyVendorBot 在 15 秒后超时”(即使显示此消息,机器人工作正常)。

在线搜索我发现似乎没有办法隐藏此消息或增加它出现的时间。所以我唯一要做的就是确保它不会出现。为此,我尝试参考此文档 article。但是显示的代码是用 C# 编写的,有人可以告诉我如何解决我的这个问题或者一些示例代码吗?

我在这里留下一个调用时间过长并生成消息的示例:

 //Mostra l'invetraio dell'armaiolo
    if (LuisRecognizer.topIntent(luisResult) === 'GetGunsmith') {
        //Take more 15 seconds
        const mod = await this.br.getGunsmith(accessdata, process.env.MemberShipType, process.env.Character);

        if (mod.error == 0) {

            var card = {
            }

            await step.context.sendActivity({
                text: 'Ecco le mod vendute oggi da Banshee-44:',
                attachments: [CardFactory.adaptiveCard(card)]
            });
        } else {
            await step.context.sendActivity("Codice di accesso scaduto.");
            await this.loginStep(step);
        }
    }

我做过类似的事情,你调用另一个函数并在函数完成后通过主动消息发送消息。就我而言,我直接在机器人内部设置函数,而不是作为单独的 Azure 函数。首先,您需要将对话参考保存在某处。我将其存储在对话状态中,并在每一轮都重新保存它(您可能可以在 onMembersAdded 中执行此操作,但我在这样做时选择了 onMessage,因此它每轮都会重新保存对话引用)。您需要为此导入 const { TurnContext } = require('botbuilder')

// In your onMessage handler
const conversationData = await this.dialogState.get(context, {});
conversationData.conversationReference = TurnContext.getConversationReference(context.activity);
await this.conversationState.saveChanges(context);

您将需要它来发送主动消息。发送 API 时,您需要发送一条消息(从技术上讲,这是可选的,但建议这样做),如果您还没有获取对话数据,请获取它,然后调用 API函数 无需等待 。如果您的 API 总是在 15 秒左右返回,您可能只需要一条标准消息(例如“等一下,我为您查找一下”),但如果它会更长,我建议您设置期望值与用户(例如,“我会帮你查一下。可能需要一分钟才能得到答案。在此期间你可以继续问我问题。”)。 您应该在轮次处理程序中进一步保存 user/conversation 状态。 由于您没有等待呼叫,轮次将结束并且机器人不会挂断或发送超时信息。这是我对我创建的模拟所做的。

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);

// That is in a switch statement. At the end of my turn handler I save state
await this.conversationState.saveChanges(context);
await this.userState.saveChanges(context);

然后是我调用的函数。因为这只是一个模拟,我只是在等待一个承诺,但显然你会打电话 await 你的 API(s)。一旦返回,您将创建一个新的 BotFrameworkAdapter 以将主动消息发送回用户。

const request = require('request-promise-native');
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('Bad Request. Please ensure your message contains the conversation reference and message text.');
            console.log(error);
        }
    }
}

module.exports.apiSimulation = apiSimulation;