【问题标题】:Empty string response due to bad synchronism由于同步不良导致空字符串响应
【发布时间】:2019-01-11 08:07:00
【问题描述】:

我启动了一个简单的代理,并添加了一个名为“myIntent”的基本 Intent。我通过 Firebase 内联编辑器启用了实现,并按照说明添加了一个名为“myFunction”的函数到提供的基础函数中。此函数包含对https://reqres.in/api/users/2 的示例 HTTPS GET 请求。
我的目标是根据对外部 API 的 GET 调用提供的响应添加对我的意图的响应。

脚本

'use strict';
 
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const https=require('https');
 
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
 
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

function myFunction(agent){
    
    var info='';
    var options = {
         host: `reqres.in`,
         path: `/api/users/2`,
         method: 'GET',
         headers: {'Accept':'application/json'}
    };
    
    var req = https.request(options, (res) => {
         console.log('statusCode:', res.statusCode);
         console.log('headers:', res.headers);
    
         let data='';
    
         res.on('data', (d) => {
           data+= d;
         });
    
         res.on('end', () => {
           console.log(data);
           let jsonObject= JSON.parse(data);
           info=jsonObject.id;
        
           console.log(JSON.stringify(info));
         });
    });

    req.on('error', (e) => {
       console.log('ERROR');
       console.error(e);
    });

    agent.add(JSON.stringify(info));
    req.write('End of request');
    req.end();  


}
    
 

    let intentMap = new Map();
    intentMap.set('myIntent',myFunction);
    agent.handleRequest(intentMap);
    });

intent 被正确触发,但我的问题是代理响应总是一个空字符串。

我在 http 调用、函数回调方面没有太多经验,但我认为问题在于线路

 agent.add(info);

我的脚本在 http 调用结束之前执行。
我在https://www.promisejs.org/ 之后尝试在myFunction 中插入一个promise,但它们都只携带错误消息。
各种帮助将不胜感激,我理解这个问题,但我无法以任何方式解决它。

PS:agent.handleRequest docs reference

我使用 Promise 失败的尝试

'use strict';

const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const https=require('https');

process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

 
 function myFunction(agent){
    var info='';
    var p=new Promise((resolve,reject)=>{
      
        var options = {
        host: `reqres.in`,
        path: `/api/users/2`,
        method: 'GET',
        headers: {'Accept':'application/json'}
        };
    
        var req = https.request(options, (res) => {
            console.log('statusCode:', res.statusCode);
            console.log('headers:', res.headers);
            let data='';
    
        res.on('data', (d) => {
            data+= d;
        });
    
        res.on('end', () => {
            console.log(data);
            let jsonObject= JSON.parse(data);
            info=jsonObject.id;
        
             console.log(JSON.stringify(info));
            });
        });

        req.on('error', (e) => {
            console.log('ERROR');
            console.error(e);
        });

        req.write('End of request');
        req.end();
        resolve(info);
    });
    
    p.then((agent)=>{
        agent.add(info);
    });

    }
let intentMap = new Map();
  intentMap.set('myIntent',myFunction);
  agent.handleRequest(intentMap);
});

【问题讨论】:

  • 你能修正你的第一个sn-p的缩进吗?

标签: javascript node.js callback promise dialogflow-es


【解决方案1】:

你仍然立即info 做事——现在解决了承诺——而不是从异步回调中做。将agent.add() 调用或resolve() 调用放在end 处理程序中,这样它只会在数据完成后发生:

var p = new Promise((resolve,reject) => {
    var options = {
        host: `reqres.in`,
        path: `/api/users/2`,
        method: 'GET',
        headers: {'Accept':'application/json'}
    };

    var req = https.request(options, (res) => {
        console.log('statusCode:', res.statusCode);
        console.log('headers:', res.headers);
        let data='';

        res.on('data', (d) => {
            data+= d;
        });

        res.on('end', () => {
            console.log(data);
            let jsonObject = JSON.parse(data);
            resolve(jsonObject.id);
//          ^^^^^^^^^^^^^^^^^^^^^^^
        });
    });

    req.on('error', (e) => {
        reject(e); // don't forget this
    });

    req.write('End of request');
    req.end();
});

p.then(info => {
//     ^^^^ the fulfillment value that you passed to resolve()
    agent.add(info);
}, err => {
    console.log('ERROR');
    console.error(err);
});

【讨论】:

  • 抱歉,这不起作用。现在控制台中有两个错误:p.then.info( /user_code/index.js:63:11) 在 process._tickDomainCallback (internal/process/next_tick.js:135:7)"。
  • @HJuls2 我不知道您正在使用什么dialogflow-fulfillment 模块或导致其中出现“未知响应类型”错误的原因,我的回答仅解决了您将info 传递给@987654328 的问题@
  • 好的,我测试了在控制台中打印值而不是使用 WebhookClient.add 并且我看到承诺正常工作。问题仅在 Dialogflow 实现功能上
  • @S.Dwyer 我的工作解决方案基本上是 Bergi 的解决方案,但我将它封装在一个返回 Promise 的函数中,即function_that_returns_promise.then(info =>{info=JSON.parse(info); agent.add(info.field)。这样,“resolve”必须有一个json字符串作为参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-27
  • 2022-10-02
  • 2011-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多