You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在基于Node.js的Microsoft Teams Bot中实现Choice Prompt步骤的重复调用(无数据场景)

Hey there! Let's adjust your Teams Bot's dialog flow so it loops back to the choice prompt when no data is found for the selected option, instead of restarting the entire dialog from scratch. Here's how to modify your code step by step:

Key Changes Explained

First, we need to:

  • Save the initial input data so we don't re-fetch it when looping back
  • Add a skip flag to bypass the getData1 step when repeating the choice selection
  • Fix a small bug in your adaptive card building logic
  • Redirect the flow back to the choice prompt when no data exists

Modified Full Code

constructor(id) { 
  super(id); 
  this.addDialog( 
    new WaterfallDialog(WATERFALL_DIALOG, [ 
      this.getData1.bind(this), 
      this.getChoice.bind(this), 
      this.getData2.bind(this), 
    ]) 
  ) 
  .addDialog(new TextPrompt(TEXT_PROMPT)) 
  .addDialog(new ChoicePrompt(CHOICE_PROMPT)); 
  this.initialDialogId = WATERFALL_DIALOG; 
} 

async getData1(stepContext) { 
  // Skip this step if we're looping back from no data in getData2
  if (stepContext.options?.skipGetData1) {
    return await stepContext.next();
  }

  if (stepContext.context.activity.text) { 
    const name = stepContext.context.activity.text; 
    // Save the initial name to dialog context so we can reuse it later
    stepContext.values.name = name;

    try {
      const response = await axios({ 
        method: 'get', 
        url: '<apiUrl>', 
        headers: { "Accept": "application/json" } 
      });
      const data = response.data; 
      let cardButtons = []; 
      let cardText = ""; 

      if (data.length > 0) { 
        data.forEach(element => { 
          cardButtons.push({ 
            type: ActionTypes.ImBack, 
            title: element.name, 
            value: element.name 
          }); 
        }); 
        cardText = `Data for ${name}.`; 
      } else { 
        cardText = "No Data Found."; 
        cardButtons = null; 
      } 

      const dataCard = CardFactory.heroCard("Data-I", null, cardButtons, { text: cardText }); 
      await stepContext.context.sendActivity({attachments: [dataCard]}); 

      const messageText = 'Select/Enter Data to View.'; 
      const msg = MessageFactory.text(messageText, messageText, InputHints.ExpectingInput); 
      return await stepContext.prompt(TEXT_PROMPT, { prompt: msg }); 
    } catch (error) { 
      console.log("Error > " + error); 
      await stepContext.context.sendActivity("Sorry, it looks like something went wrong. Please try again."); 
      return await stepContext.endDialog(); 
    }
  } else { 
    await stepContext.context.sendActivity("Sorry, it looks like something went wrong. Please try again."); 
    return await stepContext.endDialog(); 
  } 
} 

async getChoice(stepContext) { 
  return await stepContext.prompt(CHOICE_PROMPT, { 
    prompt: 'Please select the data2 options.', 
    choices: ChoiceFactory.toChoices(['Option A', 'Option B', 'Option C', 'Option D']), 
    style: ListStyle.heroCard 
  }); 
} 

async getData2(stepContext) { 
  let dataChoice = null; 
  if (stepContext.result) { 
    // ChoicePrompt returns a FoundChoice object, extract the selected value
    dataChoice = stepContext.result.value; 
  } 

  try {
    const response = await axios({ 
      method: 'get', 
      url: '<data2apiUrl>', 
      headers: { 
        'Accept': 'application/json', 
        'dataChoice': dataChoice 
      } 
    });
    const data = response.data; 
    console.log("Data KPI > ", JSON.stringify(data)); 
    const body = []; 

    if (data.length > 0) { 
      data.forEach(element => { 
        const header = { 
          "type": "Container", 
          "spacing": "medium", 
          "style": "emphasis", 
          "verticalContentAlignment": "center", 
          "items": [ 
            { 
              "type": "TextBlock", 
              "text": element.fullTitle, 
              "size": "medium", 
              "horizontalAlignment": "center", 
              "weight": "bolder", 
              "wrap": true 
            } 
          ] 
        }; 
        // Fixed: Push the header object, not the body array itself
        body.push(header); 
      }); 

      const dataCard = CardFactory.adaptiveCard({ 
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", 
        "type": "AdaptiveCard", 
        "version": "1.0", 
        "body": body 
      }); 
      await stepContext.context.sendActivity({attachments: [dataCard]}); 
      return await stepContext.endDialog(); 
    } else { 
      // No data found, trigger loop back to choice prompt
      await stepContext.context.sendActivity("Sorry, no data found for this option. Please choose another one."); 
      // Restart the dialog but skip the initial getData1 step
      return await stepContext.replaceDialog(this.initialDialogId, { skipGetData1: true }); 
    } 
  } catch (error) { 
    console.log("Error > " + error); 
    await stepContext.context.sendActivity("Sorry, it looks like something went wrong. Please try again."); 
    // Loop back to choice prompt on error too, if needed
    return await stepContext.replaceDialog(this.initialDialogId, { skipGetData1: true }); 
  } 
}

What's Changed?

  1. Skip Logic in getData1: Added a check for skipGetData1 in the first step. When this flag is passed, we jump straight to the getChoice step without re-fetching initial data.
  2. Context Data Storage: Saved the initial name to stepContext.values so we retain it when looping back (no need for users to re-enter).
  3. Choice Result Handling: Fixed extraction of the selected choice value (ChoicePrompt returns a FoundChoice object, so we use .value).
  4. Adaptive Card Bug Fix: Corrected body.push(header) instead of body.push(body) which would have caused invalid card structure.
  5. Loop Back Mechanism: When no data is found (or on API error), we send a message to the user and use replaceDialog to restart the dialog with the skipGetData1 flag, which takes us back to the choice prompt.

This way, users don't have to start over from the beginning if they pick an option with no data—they just get to choose another option immediately!

内容的提问来源于stack exchange,提问作者AJ31

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 06:42:37