您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

JavaScript 迁移快速参考JavaScript migration quick reference

适用于: SDK v4APPLIES TO: SDK v4

BotBuilder Javascript SDK v4 引入了多项基本变更,这些变更影响我们创作机器人的方式。The BotBuilder Javascript SDK v4 introduces several fundamental changes that affect how bots are authored. 本指南的目的是为用户提供快速参考,让他们了解在 v3 和 v4 SDK 中完成某个任务有哪些常见差异。The purpose of this guide is to provide a quick reference for common differences between accomplishing a task in the v3 and v4 SDKs.

  • 在机器人和通道之间传递信息的方式已改变。How information passes between a bot and channels has changed. 在 v3 中,我们使用“连接器” 和“会话” 对象。In v3, you used the connector and session objects. 在 v4 中,这些对象被“适配器” 和“轮次上下文” 对象替换。In v4, these are replaced by the adapter and turn context objects.

  • 另外,我们已将对话和机器人实例进一步分离。Also, dialogs and bot instances have been further decoupled. 在 v3 中,对话直接注册到机器人的构造函数。In v3, dialogs were registered directly in the bot's constructor. 在 v4 中,现在可以将对话作为参数传递到机器人实例中,以便更灵活地进行组合。In v4, you now pass dialogs into bot instances as arguments, providing greater compositional flexibility.

  • 另外,v4 还提供了一个 ActivityHandler 类,用于自动处理不同类型的活动,例如消息、聊天更新和事件活动。 Moreover, v4 provides an ActivityHandler class, which helps automate the handling of different types of activities, such as message, conversation update, and event activities.

这些改进导致在 Javascript 中开发机器人的语法发生了变化,尤其是在创建机器人对象、定义对话和编码事件处理逻辑方面发生了变化。These improvements result in changes in syntax for developing bots in Javascript, especially around creating bot objects, defining dialogs, and coding event handling logic.

本主题的其余部分将 JavaScript Bot Framework SDK v3 中的构造与 v4 中的相应构造进行了对比。The rest of this topic compares the constructs in the JavaScript Bot Framework SDK v3 to their equivalent in v4.

侦听传入请求To listen for incoming requests

v3v3

var connector = new builder.ChatConnector({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword
});

server.post('/api/messages', connector.listen());

v4v4

const adapter = new BotFrameworkAdapter({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword
});

server.post('/api/messages', (req, res) => {
    adapter.processActivity(req, res, async (context) => {
        await bot.run(context);
    });
});

创建机器人实例To create a bot instance

v3v3

var bot = new builder.UniversalBot(connector, [ ...DIALOG_STEPS ]);

v4v4

// Define the bot class as extending ActivityHandler.
const { ActivityHandler } = require('botbuilder');

class MyBot extends ActivityHandler {
    // ...
}

// Instantiate a new bot instance.
const bot = new MyBot(conversationState, dialog);

向用户发送消息To send a message to a user

v3v3

session.send('Hello and welcome to the help desk bot.');

v4v4

await context.sendActivity('Hello and welcome to the help desk bot.');

定义默认对话To define a default dialog

v3v3

var bot = new builder.UniversalBot(connector, [
    // Add default dialog waterfall steps...
]);

v4v4

// In the main dialog class, define a run method.
async run(turnContext, accessor) {
    const dialogSet = new DialogSet(accessor);
    dialogSet.add(this);

    const dialogContext = await dialogSet.createContext(turnContext);
    const results = await dialogContext.continueDialog();
    if (results.status === DialogTurnStatus.empty) {
        await dialogContext.beginDialog(this.id);
    }
}

// Pass conversation state management and a main dialog objects to the bot (in index.js).
const bot = new MyBot(conversationState, dialog);

// Inside the bot's constructor, add the dialog as a member property and define a DialogState property accessor.
this.dialog = dialog;
this.dialogState = this.conversationState.createProperty('DialogState');

// Inside the bot's message handler, invoke the dialog's run method, passing in the turn context and DialogState accessor.
this.onMessage(async (context, next) => {
    // Run the Dialog with the new message Activity.
    await this.dialog.run(context, this.dialogState);
    await next();
});

启动子对话To start a child dialog

子对话结束后,父对话会继续。The parent dialog resumes after the child dialog ends.

v3v3

session.beginDialog(DIALOG_ID);

v4v4

await context.beginDialog(DIALOG_ID);

替换对话To replace a dialog

新对话替换堆栈上的当前对话。The current dialog is replaced on the stack by the new dialog.

v3v3

session.replaceDialog(DIALOG_ID);

v4v4

await context.replaceDialog(DIALOG_ID);

结束对话:To end a dialog

v3v3

session.endDialog();

v4v4

可以添加一个可选的返回值。You can include an optional return value.

await context.endDialog(returnValue);

将对话注册到机器人实例To register a dialog with a bot instance

v3v3

// Create the bot.
var bot = new builder.UniversalBot(connector, [
    // ...
]};

// Add the dialog to the bot.
bot.dialog('myDialog', require('./mydialog'));

v4v4

// In the main dialog class constructor.
this.addDialog(new MyDialog(DIALOG_ID));

// In the app entry point file (index.js)
const { MainDialog } = require('./dialogs/main');

// Create the base dialog and bot, passing the main dialog as an argument.
const dialog = new MainDialog();
const reservationBot = new ReservationBot(conversationState, dialog);

提示用户输入To prompt a user for input

v3v3

var builder = require('botbuilder');
builder.Prompts.text(session, 'Please enter your destination');

v4v4

const { TextPrompt } = require('botbuilder-dialogs');

// In the dialog's constructor, register the prompt.
this.addDialog(new TextPrompt('initialPrompt'));

// In the dialog step, invoke the prompt.
return await stepContext.prompt(
    'initialPrompt', {
        prompt: 'Please enter your destination'
    }
);

检索用户对提示的响应To retrieve the user's response to a prompt

v3v3

function (session, result) {
    var destination = result.response;
    // ...
}

v4v4

// In the dialog step after the prompt step, retrieve the result from the waterfall step context.
async nextStep(stepContext) {
    const destination = stepContext.result;
    // ...
}

将信息保存到对话状态To save information to dialog state

v3v3

session.dialogData.destination = results.response;

v4v4

// In a dialog, set the value in the waterfall step context.
stepContext.values.destination = destination;

将状态更改写入持久性层To write changes in state to the persistence layer

v3v3

// State data is saved by default at the end of the turn.
// Do this to save it manually.
session.save();

v4v4

// State changes are not saved automatically at the end of the turn.
await this.conversationState.saveChanges(context, false);
await this.userState.saveChanges(context, false);

创建并注册状态存储To create and register state storage

v3v3

var builder = require('botbuilder');

// Create conversation state with in-memory storage provider.
var inMemoryStorage = new builder.MemoryBotStorage();

// Create the base dialog and bot
var bot = new builder.UniversalBot(connector, [ /*...*/ ]).set('storage', inMemoryStorage);

v4v4

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

// Create the memory layer object.
const memoryStorage = new MemoryStorage();

// Create the conversation state management object, using the storage provider.
const conversationState = new ConversationState(memoryStorage);

// Create the base dialog and bot.
const dialog = new MainDialog();
const reservationBot = new ReservationBot(conversationState, dialog);

捕获对话引发的错误To catch an error thrown from a dialog

v3v3

// Set up the error handler.
session.on('error', function (err) {
    session.send('Failed with message:', err.message);
    session.endDialog();
});

// Throw an error.
session.error('An error has occurred.');

v4v4

// Set up the error handler, using the adapter.
adapter.onTurnError = async (context, error) => {
    const errorMsg = error.message

    // Clear out conversation state to avoid keeping the conversation in a corrupted bot state.
    await conversationState.delete(context);

    // Send a message to the user.
    await context.sendActivity(errorMsg);
};

// Throw an error.
async () => {
    throw new Error('An error has occurred.');
}

注册活动处理程序To register activity handlers

v3v3

bot.on('conversationUpdate', function (message) {
    // ...
}

bot.on('contactRelationUpdate', function (message) {
    // ...
}

v4v4

// In the bot's constructor, add the handlers.
this.onMessage(async (context, next) => {
    // ...
}
  
this.onDialog(async (context, next) => {
    // ...
}

this.onMembersAdded(async (context, next) => {
    // ...
}

发送附件To send attachments

v3v3

var message = new builder.Message()
    .attachments(hotelHeroCards
    .attachmentLayout(builder.AttachmentLayout.carousel));

v4v4

await context.sendActivity({
    attachments: hotelHeroCards,
    attachmentLayout: AttachmentLayoutTypes.Carousel
});

使用自然语言识别 (LUIS)To use natural language recognition (LUIS)

v3v3

// The LUIS recognizer was part of the 'botbuilder' library
var builder = require('botbuilder');

var recognizer = new builder.LuisRecognizer(LUIS_MODEL_URL);
bot.recognizer(recognizer);

v4v4

// The LUIS recognizer is now part of the 'botbuilder-ai' library
const { LuisRecognizer } = require('botbuilder-ai');

const luisApp = { applicationId: LuisAppId, endpointKey: LuisAPIKey, endpoint: `https://${ LuisAPIHostName }` };
const recognizer = new LuisRecognizer(luisApp);

const recognizerResult = await recognizer.recognize(context);
const intent = LuisRecognizer.topIntent(recognizerResult);

v3 意向对话框和 v4 等效项v3 Intent Dialog and v4 Equivalent

v3v3

// Create a 'greetings' RegExpRecognizer that can be turned off
var greetings = new builder.RegExpRecognizer('Greetings', /hello|hi|hey|greetings/i)
    .onEnabled(function (session, callback) {
        // Check to see if this recognizer should be enabled
        if (session.conversationData.useGreetings) {
            callback(null, true);
        } else {
            callback(null, false);
        }
    });

// Create our IntentDialog and add recognizers
var intents = new builder.IntentDialog({ recognizers: [greetings] });

bot.dialog('/', intents);

// If no intent is recognized, direct user to Recognizer Menu
intents.onDefault('RecognizerMenu');

// Match our "Greetings" and "Farewell" intents with their dialogs
intents.matches('Greetings', 'Greetings');

// Add a greetings dialog
bot.dialog('Greetings', [
    function (session) {
        session.endDialog('Greetings!');
    }
]);

v4v4

this.onMessage(async (context, next) => {

    const recognizerResult = {
        text: context.activity.text,
        intents: []
    };

    const greetingRegex = RegExp(/hello|hi|hey|greetings/i);

    if (greetingRegex.test(context.activity.text)) {
      // greeting intent identified
      recognizerResult.intents.push('Greeting');
    }

    if (recognizerResult.intents.includes('Greeting')) {
        // Run the 'Greeting' dialog
        await context.beginDialog(GREETING_DIALOG_ID);
    }

    await next();
});