У меня возникла похожая проблема. Мой бот на самом деле не перестает функционировать (я, честно говоря, не уверен, если ошибка console.log будет выдана), но я получаю Couldn't send. Retry
в интерфейсе веб-чата.
Это решение не исправляет проблема, но она обеспечивает обходной путь. Я надеюсь, что если у кого-то еще есть прямое решение проблемы, он поделится им! Вместо этого вы можете сделать асинхронный вызов API и отправить ответ через проактивное сообщение. Вы можете либо явно сообщить пользователю об этом (как я это сделал в моем примере ниже), либо, если задержка не такая длительная, вам не нужно ничего говорить.
Объект цветной связи требуется для создания эта работа. Я настроил своего бота, чтобы он генерировал это для каждого сообщения (например, обработчик onMessage или onTurn, где context.activity.type === ActivityTypes.Message
, если вы используете более старый синтаксис). Я сохраняю это в состоянии разговора, чтобы иметь доступ к нему по всему боту. Вам необходимо импортировать TurnContext из библиотеки Botbuilder. Сохранение разговорной ссылки осуществляется просто с помощью
// 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. Вы бы назвали свой API там, где у меня есть await new Promise(resolve => setTimeout(resolve, 30000));
заявление. Вы действительно хотите дождаться этого звонка, поскольку вам, очевидно, потребуется ответ, чтобы отправить его обратно! Но остальная часть вашего бота продолжит функционировать. Вот вся моя примерная функция.
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. Я полагаю, вы могли бы вызвать эту конечную точку из своего бота, но мне показалось более эффективным просто создать новый адаптер для продолжения разговора.