简体   繁体   English

Javascript Firebase Firestore函数未执行

[英]Javascript firebase firestore function not executing

i try to build a ActionsOnGoogle App with the ActionsSDK, Firebase Functions and Firebase Firestore. 我尝试使用ActionsSDK,Firebase Functions和Firebase Firestore构建ActionsOnGoogle App。

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. 启动Actions App时的mainIntent,以及用户从mainIntent回答问题时的answerIntent。 Getting the text in the mainIntent from the firestore database and ask the users with the wrapped text work very fine. 从firestore数据库中获取mainIntent中的文本,并要求带有包装文本的用户工作得很好。 But then inside the function where new data is wrapped from the database array get filled. 但是,在从数据库数组中包装新数据的函数内部,就被填充了。 After executing this function the array ist empty. 执行此函数后,数组ist为空。

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. 当我查看Firebase日志时,请参阅我的自编码日志。 And there i get the following. 我得到以下内容。 First log ist latest. 第一日志管理员最新。

DEBUG: lenght 0 调试:长度0

DEBUG: Collection size: 2 调试:集合大小:2

DEBUG: document ID: answer1 = [object Object] 调试:文档ID:answer1 = [object Object]

DEBUG: ArraySize: 1 调试:ArraySize:1

DEBUG: document ID: answer2 = [object Object] 调试:文档ID:answer2 = [object Object]

DEBUG: ArraySize: 2 调试:ArraySize:2

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 问题1:处理承诺

The reason answerDocumentArray is empty at the DEBUG: lenght line is because the call to answerCollection.get() does not actually return the values. answerDocumentArrayDEBUG: lenght行处为空的原因是因为对answerCollection.get()的调用实际上未返回值。 It returns a JavaScript Promise object that will eventually resolve to the values. 它返回一个JavaScript Promise对象,该对象最终将解析为这些值。

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. 当确实解析为这些值时, then()将调用then()子句中的函数,并将开始处理返回的集合。 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. 函数完成后,它应返回另一个Promise,其中包含指示需要进一步评估的结果。 (In this case - you're not returning anything, which ends up as a null.) (在这种情况下,您将不会返回任何结果,而最终返回为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. 您可能应该做的是再创建一个then()子句,该子句将第一个传递给answerDocumentArray子句链接answerDocumentArray并使用它。 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.) (我可能已经弄错了有关Promises的解释,但是请帮自己一个忙-学习JavaScript Promises。它们仍然很痛苦,但是它们使JavaScript回调世界变得更加容易。)

But what you do with the "do stuff" part... leads to the second problem: 但是,您对“执行任务”部分所做的工作导致了第二个问题:

Problem 2: Returning values through Actions on Google 问题2:通过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). 此代码块尝试在一个循环内(实际上,在一个双循环内,但即使一个循环也足够糟糕)将值返回给Google Assistant。

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. 除非您只能保证得到一个结果,否则您将尝试app.ask()调用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 );
    }
  }
}

Actions on Google doesn't work like this, however. 但是,在Google上执行的操作无法正常工作。 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() . 该响应必须在单个ask() 单个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. 如果需要返回多个结果,则需要在循环过程中收集它们,然后仅根据收集到的结果说出一些话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM