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

answerDocumentArrayDEBUG: 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 多个结果,你需要在循环中收集它们,然后只根据你收集的结果说一些话。