Javascript firebase firestore函数未执行

时间:2017-10-30 16:49:35

标签: javascript node.js firebase actions-on-google google-cloud-firestore

我尝试使用ActionsSDK,Firebase功能和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:收藏规模:2

     

DEBUG:文件ID:answer1 = [object Object]

     

DEBUG:ArraySize:1

     

DEBUG:文件ID:answer2 = [object Object]

     

DEBUG:ArraySize:2

1 个答案:

答案 0 :(得分:4)

你有两个问题,它们都从根本上涉及了解结果如何从你正在处理的内容中传回:

问题1:使用承诺

answerDocumentArrayDEBUG: lenght为空的原因是因为对answerCollection.get()的调用实际上并未返回值。它返回一个JavaScript Promise对象,最终将解析为值。

然后,它会继续执行代码,代码中的下一行是调试行。

当它解析为这些值时,将调用then()子句中的函数并开始处理返回的集合。但这可以在调试行之后的行之后执行。当函数完成时,它应该返回另一个Promise,其中任何结果都表明需要进一步评估的内容。 (在这种情况下 - 你没有返回任何东西,最终为空。)

你应该做的是拥有另一个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回调世界更容易。)

但你对“做东西”部分的处理方式导致了第二个问题:

问题2:通过Google上的操作返回值

此代码块尝试在循环内向Google Assistant返回值(实际上,在双循环内部,但即使一个循环也足够糟糕)。

除非您只能保证一个结果,否则您将尝试多次调用app.ask()app.tell(),假设您可以为符合条件的每个文档返回一个回复满足。

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()中。你不能多次打电话给他们。如果您尝试多次调用它,结果是未定义的,但最多只能获得第一个结果。 (最糟糕的是,它会崩溃。)

如果您需要返回多个结果,则需要在完成循环时收集它们,然后根据您收集的结果只说出一些内容。