在 Node.JS 中从 fulfillment 获取 HTTP GET

Make HTTP GET from fulfillment in Node.JS

我正在尝试进行自己的 google 操作,我想调用外部 api 来获得响应。

这是我的代码:

const { conversation } = require('@assistant/conversation');
const functions = require('firebase-functions');
const app = conversation({debug:true});
const https = require('https');

app.handle('Tester', conv => {
  // Implement your code here
  conv.add("ok it works");
});

app.handle('Tester2', conv => {
  // Implement your code here
  let url = 'https://jsonplaceholder.typicode.com/users?_limit=2';
  //const url = "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22";
  
  http_req(url).then((message)=> {
    console.log(message[0].name);
      conv.add(message[0].name);
    //return Promise.resolve();
  });
});

function http_req(url) {
  return new Promise((resolve, reject) => {
      https.get(url, function(resp) {
          var json = "";
          resp.on("data", function(chunk) {
              //console.log("received JSON response: " + chunk);
              json += chunk;
          });

          resp.on("end", function() {
              let jsonData = JSON.parse(json);
                                console.log(jsonData[0].name);
                resolve(jsonData);
          });
      }).on("error", (err) => {
          reject("Error: " + err.message);
      });
  });
}

exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

日志:

错误文本:

Error: Response has already been sent. Is this being used in an async call that was not returned as a promise to the intent handler?

问题是助手不会说conv.add(message[0].name); (显然它有一个值)

提前致谢!

感谢 reddit 用户 https://www.reddit.com/r/GoogleAssistantDev/comments/lia5r4/make_http_get_from_fulfillment_in_nodejs/gn23hi3?utm_source=share&utm_medium=web2x&context=3

This error messages tells you just about all you need to know! Your call to con.add() is indeed being used in an asynchronous call (the callback chained to the Promise you created from http_req), and you are indeed not returning that Promise.

Here's what's happening:

Google calls your 'Tester2' handler

You start an asynchronous HTTP request via http_req, encapsulated in a Promise

Your function completes before the HTTP request does

Google sees that you are not returning anything from your handler and assumes that you're done, so it sends the Response

The HTTP request finishes and its Promise resolves, calling your code attached by the then() function

The simple solution here is to return the Promise created by your http_req(...).then(...) code, so Google will know that you're not just quite done, and it should wait for that Promise to resolve before sending the Response.

If you can use async/await it becomes a bit clearer:

app.handle('Tester2', async conv => {
  // Implement your code here
  let url = 'https://jsonplaceholder.typicode.com/users?_limit=2';
  //const url = "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22";

  const message = await http_req(url);
  console.log(message[0].name);
  conv.add(message[0].name);
});