无法在对话框流实现(在线编辑器)中从Firestore导入数据

时间:2019-06-27 14:43:09

标签: node.js google-cloud-firestore dialogflow actions-on-google dialogflow-fulfillment

我正在使用 Dialogflow 为Google Assistant构建操作。一切都可以,除了实现我的意图。

我正在使用 Inline Editor (由Cloud Functions for Firebase支持)来实现此目的。我的函数本身可以运行-因为我可以从函数向助手发送文本。

但是出于某种原因,代码执行从未进入 Firebase Firestore 上从我的Collection获取数据的函数-尽管 确实 < / strong>在此之前和之后执行命令。

这是我的index.js中的代码。

'use strict';
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
let db = admin.firestore();
const {dialogflow} = require('actions-on-google');
const app = dialogflow({debug: true});

app.intent('INTENT', (conv, {ENTITY}) => {
    conv.add("Hello.");         //THIS IS DISPLAYED

    db.collection("COLLECTION").orderBy("FIELD", "desc").get().then(snapshot => {
        conv.add("Hey!");       //THIS IS NOT DISPLAYED
    snapshot.forEach(doc => {
        conv.add("Hi?");        //NOR IS THIS       
    });
        conv.add("Hmm...");     //NEITHER THIS
    }).catch(error => {
        conv.add('Error!');     //NOT EVEN THIS
    });

    conv.add("Bye.");           //THIS IS DISPLAYED TOO
});

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

很显然,这表明执行从未真正进入db...块,因此该功能甚至没有引发任何错误。

这是Firebase的日志。

Function execution started
Billing account not configured...
Warning, estimating Firebase Config based on GCLOUD_PROJECT. Initializing firebase-admin may fail
Request {...}
Headers {...}
Conversation {...}
Response {...}
Function execution took 1681 ms, finished with status code: 200

我知道firestore函数异步获取数据,但是在那里 似乎即使在其.then(...)块中也无法执行任何操作。

我还尝试returnPromise块中提取一个.then(...),并使用第二个.then(...)-再次不起作用。

var fetch = db.collection("COLLECTION").orderBy("FIELD", "desc").get().then(snapshot => {
    conv.add("Hey!");                    //NOT DISPLAYED
    var responseArr = [];
    snapshot.forEach(doc => {
        conv.add("Hi?");                 //NOT DISPLAYED  
        responseArr.push(doc);  
    });
    conv.add("Hmm...");                  //NOT DISPLAYED
    return Promise.resolve(responseArr);
}).then(fetch => {
    conv.add("Here?");                   //NOT DISPLAYED
}).catch(error => {
    conv.add('Error!');                  //NOT DISPLAYED
});

最后,我还尝试将firestore函数放在单独的function中,像这样。

function getData(){
    return db.collection("COLLECTION").orderBy("FIELD", "desc").get().then(snapshot => {
        snapshot.forEach(doc => {
            ...    
        });

        return data;                //Manipulated from above. 'data' can be a string.
    }).catch(error => {
           return error;
    });
}

app.intent('INTENT', (conv, {ENTITY}) => {
    conv.add("Hello.");         //THIS IS DISPLAYED

    conv.add(getData());        //THIS IS NOT DISPLAYED

    conv.add("Bye.");           //THIS IS DISPLAYED
});

1 个答案:

答案 0 :(得分:2)

问题在于您正在执行异步操作(对get()的调用),但没有从Intent Handler本身返回Promise。该库要求您返回一个Promise,以便它知道正在进行异步操作。

从内部{em> 返回一个then()部分是不够的-这不会从处理程序中返回值,而只是返回传递给下一个{ {1}}函数或(如果是最后一个)作为整个Promise链的返回值。

在您的原始代码中,只需返回then()链即可完成此操作。像这样的第一行:

get().then().catch()

在第二个示例中,return db.collection("COLLECTION").orderBy("FIELD", "desc").get() // etc etc 块中的fetch不是您认为的then(),只会使事情变得混乱。通过这种结构,您需要从fetch分配中返回fetch

您的第三个示例更加复杂。线

let
从表面上看,

甚至看起来都不可行,因为它返回了Promise,但是您不能向conv.add(getData()); 对象添加承诺。您需要将该部分重写为

conv

但是,这并没有解决“再见”行的工作方式。如果您确实想在数据后添加“ Bye”,则必须将其作为return getData() .then( data => conv.add( data ) ); 块的一部分。

简而言之,在处理异步数据时,您需要

  1. 确保您了解Promises的工作原理,并确保使用Promises完成所有异步工作。
  2. 将所有数据添加到Promise的then()部分
  3. 正确返回承诺