繁体   English   中英

如何在不每次在 Microsoft Bot Framework Direct Line JS Client (REACTJS) 中创建直线对象的情况下从服务器获得响应

[英]How can I get response from the server without creating directline object everytime in Microsoft Bot Framework Direct Line JS Client (REACTJS)

我在 useEffect 中使用userInput作为依赖数组传递getResponse()函数。 每次用户发送输入时,都会触发此功能,并且每次都会创建新的直达线对象。 我面临的问题是我每次向机器人发送请求时都在创建机器人。 如何在初始渲染时只创建一次对象,然后使用该对象与机器人连接。

请帮忙!

这是我正在关注的 botframework 文档

这是我编写的用于在 ReactJS 中与机器人通信的代码。

import React, { useEffect, useState } from "react";
import "./App.css"
import { DirectLine } from "botframework-directlinejs";
import { browserName, browserVersion, osName } from "react-device-detect";
import { ConnectionStatus } from 'botframework-directlinejs';
import Header from "./Components/Header";
import MainBody from "./Components/MainBody";
import BottomWrapper from "./Components/BottomWrapper";

function App() {
  useEffect(() => {
    const userIpDetails = fetchIp();
    setUserIp(userIpDetails);
  }, []);

  // to fetch user IP
  const fetchIp = async () => {
    const response = await fetch("https://api.ipify.org/?format=json");
    const ip = await response.json();
    const userIP = ip.ip;
    return userIP;
  };

  const [loaded, setLoaded] = useState(false);
  const [message, setMessage] = useState("");
  const [userInput, setUserInput] = useState([]);
  const [messages, setMessages] = useState([]);
  const [userIp, setUserIp] = useState("");

  var client;

  useEffect(() => {
    setLoaded(true);
    getResponse();
  }, [userInput]);

  // to get DirectLine Streaming Token
  const getDirectLineStreamingToken = async function () {
    const res = await fetch(
      https://directline.botframework.com/v3/directline/tokens/generate,
      {
        method: "POST",
        headers: {
          Authorization:
            `Bearer TOKEN`,
        },
      }
    );
    const { token } = await res.json();
    return token;
  };

  // send request via message box
  const sendRequest = () => {
    console.log("request sent");
    client
      ?.postActivity({
        from: {
          id: "my_id",
          name: "Software Company",
          avatarUrl:
            "https://demos.telerik.com/kendo-ui/content/chat/VacationBot.png",
        },
        type: "message",
        text: message,
        channelData: {
          iP: userIp,
          platform: `${osName}`,
          Browser: `${browserName} ${browserVersion}`,
        },
      })
      ?.subscribe(
        (id) => console.log("Posted activity, assigned ID ", id),
        (error) => console.log("Error posting activity", error)
      );
  };

  // receive response from server
  const getResponse = function () {
    getDirectLineStreamingToken().then(function (token) {
      client = new DirectLine({
        domain: "https://directline.botframework.com/v3/directline",
        token: token,
      });

      client.activity$.subscribe((activity) => {
        onResponse(activity);
      });

      client.connectionStatus$
      .subscribe(connectionStatus => {
          switch(connectionStatus) {
              case ConnectionStatus.Uninitialized:    // the status when the DirectLine object is first created/constructed
              case ConnectionStatus.Connecting:       // currently trying to connect to the conversation
              case ConnectionStatus.Online:           // successfully connected to the converstaion. Connection is healthy so far as we know.
              case ConnectionStatus.ExpiredToken:     // last operation errored out with an expired token. Your app should supply a new one.
              case ConnectionStatus.FailedToConnect:  // the initial attempt to connect to the conversation failed. No recovery possible.
              case ConnectionStatus.Ended:            // the bot ended the conversation
          }
          console.log("connection status ", connectionStatus)
      });
    })
    .catch((e) => console.log("bot error", e));;
  };

  // handle response received from server
  const onResponse = function (activity) {
    console.log("activity is ", activity);
    let receivedResponse = activity.text;
    if (activity.inputHint === "acceptingInput") {
      setMessages([
        ...messages,
        { messageKey: receivedResponse, isbotmessage: true },
      ]);
    }
  };

  const handleChange = function (event) {
    setMessage(event.target.value);
    console.log(event.target.value);
  };

  const handleKeyPress = function (event) {
    if (event.key === "Enter") {
      sendRequest();
      setMessages([...messages, { messageKey: message, isbotmessage: false }]);
      setUserInput([
        ...messages,
        { messageKey: userInput, isbotmessage: false },
      ]);
    }
  };

  const handleClick = function (event) {
    sendRequest();
    setMessages([...messages, { messageKey: message, isbotmessage: false }]);
    setUserInput([...messages, { messageKey: userInput, isbotmessage: false }]);
  };

  return loaded ? (
    <div className="App">
      <div className="chat-window">
        <Header />
        <MainBody messages={messages}/>
        <BottomWrapper message={message} handleChange={handleChange} handleKeyPress={handleKeyPress} handleClick={handleClick}/>
      </div>
    </div>
  ) : (
    <p>Loading...</p>
  );
}

export default App;

您应该将 DirectLine client对象的创建以及订阅activityconnectionStatus移出函数,或者将 useEffect() 挂钩配置为仅运行一次。 client对象应创建一次,然后根据需要进行引用。 查看这篇讨论如何实现这些选项的 SO帖子

此外,因为您已经订阅了activityconnectionStatus ,所以应该允许它们独立运行,以便它们可以按预期运行。 connectionStatus发生变化时,switch 语句会检测到这一点。 当遇到不同的情况时,您可以通过useState()分配状态并通过useEffect()挂钩检测状态的更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM