Javascript firebase firestore 函数未执行
Javascript firebase firestore function not executing
我尝试使用 ActionsSDK、Firebase Functions 和 Firebase Firestore 构建一个 ActionsOnGoogle 应用程序。
我建立了一个必须有意图的实现。启动 Actions App 时的 mainIntent 和用户从 mainIntent 回答问题时的 answerIntent。从 firestore 数据库中获取 mainIntent 中的文本,并使用包装文本询问用户,效果非常好。但是然后在从数据库数组中包装新数据的函数内部得到填充。执行此函数后,数组为空。
这是我的代码:
function answerIntent(app){
console.log('DEBUG: answerIntent acsess');
console.log('DEBUG: ' + partAwnserRef);
var rawInput = app.getRawInput();
var answerCollection = db.collection(partAwnserRef);
var answers = answerCollection.get().then(collection => {
console.log('DEBUG: Collection size: ' + collection.size);
collection.forEach(document => {
if(document.exists){
console.log('DEBUG: document ID: ' + document.id + ' = ' + document.data());
answerDocumentArray.push(document);
console.log('DEBUG: ArraySize: ' + answerDocumentArray.length);
//HERE MY ARRAY WAS FILLED CORRECTLY
}
else{
console.log('DEBUG: Dokument existiert nicht;');
app.tell('Es liegt ein Fehler vor!');
}
});
})
.catch(err => {
console.log('DEBUG: Es ist ein Fehler aufgetretten ' + err);
app.tell('Es liegt ein Fehler vor!');
});
//HERE THE OUTPOT IN THE LOG SAY THE ARRAY IS EMPTY
console.log("DEBUG: lenght " + answerDocumentArray.length);
for(var i = 0; i < answerDocumentArray.length; i++){
var propertyNameArray = [];
for(var propertyName in answerDocumentArray[i]){
propertyNameArray.push(propertyName);
console.log('DEBUG: propertyName: ' + propertyName);
}
for(var j = 0; j < propertyNameArray.length; j++){
if(propertyNameArray[j].includes('answer')){
if(rawInput.includes(answerDocumentArray[i].propertyNameArray[j])){
app.tell(answerDocumentArray[i].propertyNameArray[j]);
}
else{
var inputPrompt = app.buildInputPrompt(false, 'Ich habe die leider nicht verstanden!', ['Kannst du deine Antwort wiederholen?']);
app.ask(inputPrompt);
}
}
}
}
};
当我查看 firebase 日志时,会看到我的自编码日志。我得到以下信息。第一个日志是最新的。
DEBUG: lenght 0
DEBUG: Collection size: 2
DEBUG: document ID: answer1 = [object Object]
DEBUG: ArraySize: 1
DEBUG: document ID: answer2 = [object Object]
DEBUG: ArraySize: 2
您有两个问题,这两个问题从根本上都涉及了解结果如何从您正在处理的内容传回:
问题 1:使用 Promise
answerDocumentArray
在 DEBUG: lenght
行为空的原因是因为对 answerCollection.get()
的调用实际上并没有 return 值。它 return 是一个 JavaScript Promise 对象,最终将解析为值。
然而,直到它执行,它会继续执行代码,代码中的下一行是调试行。
当它解析为这些值时,then()
子句中的函数将被调用并开始处理集合 returned。但这可能会在调试行之后的行之后执行。当函数完成时,它应该 return 另一个 Promise,其结果表明需要进一步评估的内容。 (在这种情况下 - 你没有 returning 任何东西,它最终为 null。)
您可能应该做的是有另一个 then()
子句链接第一个通过 answerDocumentArray
并使用它的子句。大致是这样的:
var answers = answerCollection.get().then( collection =>{
console.log( 'DEBUG: Collection size: ' + collection.size );
collection.forEach( document =>{
if( document.exists
){
console.log( 'DEBUG: document ID: ' + document.id + ' = ' + document.data() );
answerDocumentArray.push( document );
console.log( 'DEBUG: ArraySize: ' + answerDocumentArray.length );
//HERE MY ARRAY WAS FILLED CORRECTLY
}
else{
console.log( 'DEBUG: Dokument existiert nicht;' );
app.tell( 'Es liegt ein Fehler vor!' );
}
} )
return Promise.resolve( answerDocumentArray );
;
} )
.then( answers => {
for( var i = 0; i < answers.length; i++ ){
// ... Do stuff with the answers here
}
})
.catch( err =>{
console.log( 'DEBUG: Es ist ein Fehler aufgetretten ' + err );
app.tell( 'Es liegt ein Fehler vor!' );
} )
;
(我可能搞砸了关于 Promises 的解释,但帮自己一个忙 - 学习 JavaScript Promises。它们仍然很痛苦,但它们让 JavaScript 回调世界变得更容易。)
但是你对 "do stuff" 部分所做的...导致了第二个问题:
问题 2:通过 Google
上的操作返回值
此代码块尝试在一个循环内(实际上,在双循环内,但即使是一个循环也够糟糕)将 return 值传递给 Google 助手。
除非您只能保证一个结果,否则您将尝试多次调用 app.ask()
或 app.tell()
,假设您可以 return 每个文档一个响应符合您所满足的条件。
for( var j = 0; j < propertyNameArray.length; j++ ){
if( propertyNameArray[j].includes( 'answer' ) ){
if( rawInput.includes( answerDocumentArray[i].propertyNameArray[j] ) ){
app.tell( answerDocumentArray[i].propertyNameArray[j] );
}
else{
var inputPrompt = app.buildInputPrompt( false, 'Ich habe die leider nicht verstanden!', ['Kannst du deine Antwort wiederholen?'] );
app.ask( inputPrompt );
}
}
}
但是,Google 上的操作并非如此。每次调用您的 Intent 时,您只能向用户发送 单个 响应。该响应必须在单个 ask()
或 单个 tell()
中。您不能多次调用它们。如果您尝试多次调用它,结果是不确定的,但充其量您只会得到第一个结果。 (最坏的情况下,它会崩溃。)
如果你需要 return 多个结果,你需要在循环中收集它们,然后只根据你收集的结果说一些话。
我尝试使用 ActionsSDK、Firebase Functions 和 Firebase Firestore 构建一个 ActionsOnGoogle 应用程序。
我建立了一个必须有意图的实现。启动 Actions App 时的 mainIntent 和用户从 mainIntent 回答问题时的 answerIntent。从 firestore 数据库中获取 mainIntent 中的文本,并使用包装文本询问用户,效果非常好。但是然后在从数据库数组中包装新数据的函数内部得到填充。执行此函数后,数组为空。
这是我的代码:
function answerIntent(app){
console.log('DEBUG: answerIntent acsess');
console.log('DEBUG: ' + partAwnserRef);
var rawInput = app.getRawInput();
var answerCollection = db.collection(partAwnserRef);
var answers = answerCollection.get().then(collection => {
console.log('DEBUG: Collection size: ' + collection.size);
collection.forEach(document => {
if(document.exists){
console.log('DEBUG: document ID: ' + document.id + ' = ' + document.data());
answerDocumentArray.push(document);
console.log('DEBUG: ArraySize: ' + answerDocumentArray.length);
//HERE MY ARRAY WAS FILLED CORRECTLY
}
else{
console.log('DEBUG: Dokument existiert nicht;');
app.tell('Es liegt ein Fehler vor!');
}
});
})
.catch(err => {
console.log('DEBUG: Es ist ein Fehler aufgetretten ' + err);
app.tell('Es liegt ein Fehler vor!');
});
//HERE THE OUTPOT IN THE LOG SAY THE ARRAY IS EMPTY
console.log("DEBUG: lenght " + answerDocumentArray.length);
for(var i = 0; i < answerDocumentArray.length; i++){
var propertyNameArray = [];
for(var propertyName in answerDocumentArray[i]){
propertyNameArray.push(propertyName);
console.log('DEBUG: propertyName: ' + propertyName);
}
for(var j = 0; j < propertyNameArray.length; j++){
if(propertyNameArray[j].includes('answer')){
if(rawInput.includes(answerDocumentArray[i].propertyNameArray[j])){
app.tell(answerDocumentArray[i].propertyNameArray[j]);
}
else{
var inputPrompt = app.buildInputPrompt(false, 'Ich habe die leider nicht verstanden!', ['Kannst du deine Antwort wiederholen?']);
app.ask(inputPrompt);
}
}
}
}
};
当我查看 firebase 日志时,会看到我的自编码日志。我得到以下信息。第一个日志是最新的。
DEBUG: lenght 0
DEBUG: Collection size: 2
DEBUG: document ID: answer1 = [object Object]
DEBUG: ArraySize: 1
DEBUG: document ID: answer2 = [object Object]
DEBUG: ArraySize: 2
您有两个问题,这两个问题从根本上都涉及了解结果如何从您正在处理的内容传回:
问题 1:使用 Promise
answerDocumentArray
在 DEBUG: lenght
行为空的原因是因为对 answerCollection.get()
的调用实际上并没有 return 值。它 return 是一个 JavaScript Promise 对象,最终将解析为值。
然而,直到它执行,它会继续执行代码,代码中的下一行是调试行。
当它解析为这些值时,then()
子句中的函数将被调用并开始处理集合 returned。但这可能会在调试行之后的行之后执行。当函数完成时,它应该 return 另一个 Promise,其结果表明需要进一步评估的内容。 (在这种情况下 - 你没有 returning 任何东西,它最终为 null。)
您可能应该做的是有另一个 then()
子句链接第一个通过 answerDocumentArray
并使用它的子句。大致是这样的:
var answers = answerCollection.get().then( collection =>{
console.log( 'DEBUG: Collection size: ' + collection.size );
collection.forEach( document =>{
if( document.exists
){
console.log( 'DEBUG: document ID: ' + document.id + ' = ' + document.data() );
answerDocumentArray.push( document );
console.log( 'DEBUG: ArraySize: ' + answerDocumentArray.length );
//HERE MY ARRAY WAS FILLED CORRECTLY
}
else{
console.log( 'DEBUG: Dokument existiert nicht;' );
app.tell( 'Es liegt ein Fehler vor!' );
}
} )
return Promise.resolve( answerDocumentArray );
;
} )
.then( answers => {
for( var i = 0; i < answers.length; i++ ){
// ... Do stuff with the answers here
}
})
.catch( err =>{
console.log( 'DEBUG: Es ist ein Fehler aufgetretten ' + err );
app.tell( 'Es liegt ein Fehler vor!' );
} )
;
(我可能搞砸了关于 Promises 的解释,但帮自己一个忙 - 学习 JavaScript Promises。它们仍然很痛苦,但它们让 JavaScript 回调世界变得更容易。)
但是你对 "do stuff" 部分所做的...导致了第二个问题:
问题 2:通过 Google
上的操作返回值此代码块尝试在一个循环内(实际上,在双循环内,但即使是一个循环也够糟糕)将 return 值传递给 Google 助手。
除非您只能保证一个结果,否则您将尝试多次调用 app.ask()
或 app.tell()
,假设您可以 return 每个文档一个响应符合您所满足的条件。
for( var j = 0; j < propertyNameArray.length; j++ ){
if( propertyNameArray[j].includes( 'answer' ) ){
if( rawInput.includes( answerDocumentArray[i].propertyNameArray[j] ) ){
app.tell( answerDocumentArray[i].propertyNameArray[j] );
}
else{
var inputPrompt = app.buildInputPrompt( false, 'Ich habe die leider nicht verstanden!', ['Kannst du deine Antwort wiederholen?'] );
app.ask( inputPrompt );
}
}
}
但是,Google 上的操作并非如此。每次调用您的 Intent 时,您只能向用户发送 单个 响应。该响应必须在单个 ask()
或 单个 tell()
中。您不能多次调用它们。如果您尝试多次调用它,结果是不确定的,但充其量您只会得到第一个结果。 (最坏的情况下,它会崩溃。)
如果你需要 return 多个结果,你需要在循环中收集它们,然后只根据你收集的结果说一些话。