Невозможно передать данные из Firestore в Dialogflow Fulfillment (встроенный редактор)

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

Я использую Встроенный редактор (на базе облачных функций для Firebase) для выполнения намерения. Моя функция сама по себе работает — так как я могу отправить текст помощнику из функции.

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

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

Как было сказано, если другой ответ не отвечает на ваш вопрос, продолжайте и спроси новый. Редактировать вопрос недостаточно, но если другой ответ не помогает — задайте его еще раз, уточнив, какая часть другого ответа не имеет смысла.

Prisoner 27.06.2019 18:03

@Prisoner Конечно, спасибо! Кажется, вы ответили на вопрос оригинальный — было бы здорово, если бы вы могли помочь.

Mrigank Pawagi 27.06.2019 18:15

А что это не отвечает на ваш вопрос?

Prisoner 27.06.2019 18:16

@Prisoner Я прочитал еще пару ответов, которые тоже случайно написали вы. С этой ссылкой я return добавил Promise в блок .then(...) и добавил второй блок .then(...) — но разницы нет.

Mrigank Pawagi 27.06.2019 18:29

Повторно опубликуйте вопрос с тем, что вы пробовали, и я дам более развернутый ответ.

Prisoner 27.06.2019 19:03

@Prisoner Я обновил ответ. Пожалуйста, скажите мне, есть ли что-нибудь, что мне нужно предоставить.

Mrigank Pawagi 28.06.2019 13:23

@Prisoner Я полагаю, что, поскольку у вас есть [золотой] значок actions-on-google, вы можете в одиночку повторно открыть вопрос. Репост будет дублировать мой собственный вопрос.

Mrigank Pawagi 28.06.2019 15:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
491
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Возврата промиса из внутри части 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. Убедитесь, что вы понимаете, как работают промисы, и убедитесь, что вся асинхронная работа выполняется с использованием промисов.
  2. Добавьте все свои данные в часть обещания then().
  3. Вернуть обещание правильно

Большое спасибо! return getData().then( data => conv.add( data ) ); сработало для меня так хорошо! Обещания для меня просто кошмар...

Mrigank Pawagi 28.06.2019 18:14

Другие вопросы по теме