Я использую Диалоговый поток для создания Действие для 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 Конечно, спасибо! Кажется, вы ответили на вопрос оригинальный — было бы здорово, если бы вы могли помочь.
А что это не отвечает на ваш вопрос?
@Prisoner Я прочитал еще пару ответов, которые тоже случайно написали вы. С этой ссылкой я return добавил Promise в блок .then(...) и добавил второй блок .then(...) — но разницы нет.
Повторно опубликуйте вопрос с тем, что вы пробовали, и я дам более развернутый ответ.
@Prisoner Я обновил ответ. Пожалуйста, скажите мне, есть ли что-нибудь, что мне нужно предоставить.
@Prisoner Я полагаю, что, поскольку у вас есть [золотой] значок actions-on-google, вы можете в одиночку повторно открыть вопрос. Репост будет дублировать мой собственный вопрос.





Проблема в том, что вы выполняете асинхронную операцию (вызов 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().
Короче говоря, при работе с асинхронными данными вам необходимо
then().Большое спасибо! return getData().then( data => conv.add( data ) ); сработало для меня так хорошо! Обещания для меня просто кошмар...
Как было сказано, если другой ответ не отвечает на ваш вопрос, продолжайте и спроси новый. Редактировать вопрос недостаточно, но если другой ответ не помогает — задайте его еще раз, уточнив, какая часть другого ответа не имеет смысла.