Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在对话流中从firebase数据库检索值_Firebase_Firebase Realtime Database_Google Cloud Functions_Actions On Google - Fatal编程技术网

在对话流中从firebase数据库检索值

在对话流中从firebase数据库检索值,firebase,firebase-realtime-database,google-cloud-functions,actions-on-google,Firebase,Firebase Realtime Database,Google Cloud Functions,Actions On Google,在对话流中调用特定意图后,我试图从firebase数据库中获取信息。 我正在尝试创建一个函数,它接受一个用户ID参数,然后它将获得该用户的高分,然后将该用户的高分返回给他们 app.intent('get-highscore', (conv) => { var thisUsersHighestscore = fetchHighscoreByUserId(conv.user.id); conv.ask('your highest score is ${thisUsersHighes

在对话流中调用特定意图后,我试图从firebase数据库中获取信息。 我正在尝试创建一个函数,它接受一个用户ID参数,然后它将获得该用户的高分,然后将该用户的高分返回给他们

app.intent('get-highscore', (conv) => {
  var thisUsersHighestscore = fetchHighscoreByUserId(conv.user.id);

  conv.ask('your highest score is ${thisUsersHighestScore}, say continue to keep playing.');

});



function fetchHighscoreByUserId(userId){
  var highscoresRef = database.ref("highscores");
  var thisUsersHighscore;

  highscoresRef.on('value',function(snap){

    var allHighscores= snap.val();
    thisUsersHighscore = allHighscores.users.userId.highscore;

  });
  return thisUsersHighscore;

}
数据库中的数据示例:

 "highscores" : {
    "users" : {
      "1539261356999999924819020" : {
        "highscore" : 2,
        "nickname" : "default"
      },
      "15393362381293223232222738" : {
        "highscore" : 78,
        "nickname" : "quiz master"
      },
      "15393365724084067696560" : {
        "highscore" : "32",
        "nickname" : "cutie pie"
      },
      "45343453535534534353" : {
        "highscore" : 1,
        "nickname" : "friendly man"
      }
    }
  }

似乎它从未在我的函数中设置任何值给
thisUsersHighScore。

您在这里遇到了许多问题,包括如何使用Firebase、如何在Google上使用操作以及如何使用Javascript。这些问题中的一些只是你可以做得更好、更有效率,而另一些则会造成实际问题

访问JavaScript结构中的值


第一个问题是,
allHighscores.users.userId.highscores
的意思是“在名为'allHighscores'的对象中,获取名为'users'的属性,从该结果中获取名为'userId'的属性”。但是没有名为“userId”的属性——只有一组以数字命名的属性

您可能想要更像
allHighscores.users[userId].highscore的东西,这意味着“在名为'allHighscores'的对象中,获取名为'users'的属性,从该结果中,获取名为'userId'的属性”

但如果这有数千或几十万条记录,这将占用大量内存。从Firebase取回要花很多时间。如果您直接从Firebase获取一条记录,不是更好吗

两个Firebase问题

从上面看,您可能应该从Firebase中获取一条记录,而不是整个表,然后搜索所需的一条记录。在firebase中,这意味着您获得对所需数据路径的引用,然后请求该值

要指定所需的路径,可以执行以下操作

var userRef = database.ref("highscores/users").child(userId);
var userScoreRef = userRef.child( "highscore" );
(当然,你可以把它们放在一份声明中。为了清楚起见,我这样把它们分开了。)

但是,一旦有了引用,就需要读取该引用处的数据。这里有两个问题

  • 您使用的是
    on()
    方法,该方法只获取一次值,然后还设置了一个回调,以便在每次分数更新时调用。您可能不需要后者,因此可以使用
    once()
    方法一次性获取值

  • 您有一个回调函数设置来获取值(这很好,因为这是一个异步操作,这是Javascript中处理异步操作的传统方法),但您返回的是回调之外的值。所以你总是返回一个空值

  • 这些建议表明,您还需要将
    fetchHighScoreByUserId()
    设置为一个异步函数,我们现在要做的就是返回一个承诺。当异步函数完成时,此承诺将解析为实际值。幸运的是,Firebase库可以返回一个承诺,我们可以将其值作为响应中
    .then()
    子句的一部分来获取,因此我们可以简化很多事情。(我强烈建议您阅读Javascript中的承诺以及如何使用它们。)它可能看起来像这样:

    return userScoreRef.once("value")
      .then( function(scoreSnapshot){
        var score = scoreSnapshot.val();
        return score;
      } );
    
    app.intent('get-highscore', (conv) => {
      return fetchHighscoreByUserId(conv.user.id)
        .then( function(highScore){
          conv.ask(`Your highest score is ${highScore}. Do you want to play again?`);
        } );
    });
    
    谷歌上的异步函数和操作

    在Intent处理程序中,您遇到了与上面类似的问题。对
    fetchHighScoreByUserId()
    的调用是异步的,因此在调用
    conv.ask()
    或从函数返回时,它不会完成运行(或返回值)。AoG需要知道如何等待异步调用完成。它怎么能做到呢?再次承诺

    如果涉及asyc调用,AoG意图处理程序必须返回承诺

    由于修改后的
    fetchHighScoreByUserId()
    返回一个承诺,我们将利用它。我们还将在承诺链的
    .then()
    部分设置我们的响应。它可能看起来像这样:

    return userScoreRef.once("value")
      .then( function(scoreSnapshot){
        var score = scoreSnapshot.val();
        return score;
      } );
    
    app.intent('get-highscore', (conv) => {
      return fetchHighscoreByUserId(conv.user.id)
        .then( function(highScore){
          conv.ask(`Your highest score is ${highScore}. Do you want to play again?`);
        } );
    });
    
    这里有两个旁白:

  • 如果您试图像那样使用${highScore},则需要使用backticks“`”来定义字符串

  • 短语“如果你想再次播放,请说继续。”是一个非常糟糕的语音用户界面。更好的办法是直接询问他们是否想再次比赛


  • “allhighscore.users.userId.highscore;”不反映代码段底部的JSON对象。我是对的吗?我想是的,userId是我在函数中传递的值。也许我把语法搞错了