Невозможно перенести данные из Firestore в выполнение Dialogflow (встроенный редактор) - PullRequest
2 голосов
/ 27 июня 2019

Я использую Dialogflow , чтобы создать Действие для Google Assistant .Все работает, кроме выполнения моего намерения.

Я использую Inline Editor (Powered by Cloud Functions for Firebase) для выполнения намерения.Моя функция сама по себе работает - так как я могу отправить текст помощнику из функции.

Но по какой-то причине выполнение кода никогда не входит в функцию, которая извлекает данные из моего Collection в Firebase Firestore - хотя делает Выполнять команды до и после.

Вот код в моем 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(...).

Я также пытался return извлечь Promise из.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 Ответ

2 голосов
/ 28 июня 2019

Проблема в том, что вы выполняете асинхронную операцию (вызов get()), но не возвращаете Promise от самого обработчика намерений. Библиотека требует от вас вернуть Promise, чтобы она знала, что выполняется асинхронная операция.

Возвращение Promise из внутри части then() недостаточно - это не возвращает значение из обработчика, оно просто возвращает значение, которое передается следующей функции then() или (если он был последним) в качестве возвращаемого значения всей цепочки Promise.

В вашем исходном коде это можно сделать, просто вернув цепочку get().then().catch(). Примерно так, как в первой строке:

return db.collection("COLLECTION").orderBy("FIELD", "desc").get() // etc etc

Во втором примере fetch в вашем блоке then() - это не fetch, как вы думаете, а только путаница. Таким образом, вам нужно вернуть fetch из присваивания let.

Ваш третий пример более сложный. Линия

conv.add(getData());

даже не кажется, что он будет работать на поверхности, потому что он возвращает Обещание, но вы не можете добавить обещание к объекту conv. Вам нужно будет переписать эту часть как

return getData()
  .then( data => conv.add( data ) );

Но это не относится к тому, как будет работать строка "Пока". Если вы действительно хотите «пока» после данных, вам нужно будет включить его как часть блока then().

Короче говоря, при работе с асинхронными данными необходимо

  1. Убедитесь, что вы понимаете, как работают Promises, и убедитесь, что вся асинхронная работа выполняется с помощью Promises.
  2. Добавьте все свои данные в часть then() Обещания
  3. Верните обещание правильно
...