Javascript firebase firestore function not executing

烂漫一生 提交于 2020-01-06 08:02:53

问题


i try to build a ActionsOnGoogle App with the ActionsSDK, Firebase Functions and Firebase Firestore.

I build a fulfillment that haves to intents. The mainIntent when starting the Actions App and the answerIntent when the users answers the question from the mainIntent. Getting the text in the mainIntent from the firestore database and ask the users with the wrapped text work very fine. But then inside the function where new data is wrapped from the database array get filled. After executing this function the array ist empty.

This is my code:

    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); 
          }
        }
      }
    }
   };

When i look inside the firebase logs is see my self coded logs. And there i get the following. First log ist latest.

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:


You have two problems, both of them fundamentally involve understanding how results get passed back from what you're working on:

Problem 1: Working with Promises

The reason answerDocumentArray is empty at the DEBUG: lenght line is because the call to answerCollection.get() does not actually return the values. It returns a JavaScript Promise object that will eventually resolve to the values.

Until it does, however, it will keep executing the code, and the next line in the code is the debugging line.

When it does resolve to those values, the function in the then() clause will be called and will start processing the collection returned. But this may be executed after the lines following the debugging line. When the function completes, it should return another Promise with any results indicating what needs to be further evaluated. (In this case - you're not returning anything, which ends up as a null.)

What you should likely do is have another then() clause that chains off the first one that is passed the answerDocumentArray and works with it. Something roughly like this:

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!' );
  } )
  ;

(I may have mangled the explanation about Promises, but do yourself a favor - learn JavaScript Promises. They're still a pain, but they make JavaScript callbacks worlds easier.)

But what you do with the "do stuff" part... leads to the second problem:

Problem 2: Returning values through Actions on Google

This code block attempts to return values to the Google Assistant inside a loop (actually, inside a double-loop, but even one loop is bad enough).

Unless you can guarantee only one result, you're going to try and call either app.ask() or app.tell() more than once, assuming you can return one response for each document that matches the conditions that you meet.

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 );
    }
  }
}

Actions on Google doesn't work like this, however. You can only send a single response to the user for each time your Intent is called. That response must be in a single ask() or a single tell(). You can't call them multiple times. If you try calling it multiple times, the results are undefined, but at best, you'll only get the first result. (At worst, it will crash.)

If you need to return multiple results, you need to collect them as you go through the loop and then only say something based on the result of what you've collected.



来源:https://stackoverflow.com/questions/47020388/javascript-firebase-firestore-function-not-executing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!