Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/472.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
Javascript 如何从FirebaseListObservable映射和减少子值_Javascript_Angular_Firebase_Firebase Realtime Database_Angularfire2 - Fatal编程技术网

Javascript 如何从FirebaseListObservable映射和减少子值

Javascript 如何从FirebaseListObservable映射和减少子值,javascript,angular,firebase,firebase-realtime-database,angularfire2,Javascript,Angular,Firebase,Firebase Realtime Database,Angularfire2,我试图总结考试成绩,我的数据如下 { testResult: { foo: {foo1: x}, {foo2: y} }, { bar: {bar1: z} let res = this._dbref.database.list('/bmzi-answers',{ query: { orderByKey: true, equalTo: id

我试图总结考试成绩,我的数据如下

   { testResult: 
      { foo:
         {foo1: x},
         {foo2: y}
      },
      { bar:
         {bar1: z}
let res = this._dbref.database.list('/bmzi-answers',{
      query: {
        orderByKey: true,
        equalTo: id
      }
    })
“foo”和“bar”是有意义的问题子类别,子节点包含问题ID和相应的分数。我需要按类别总结分数。我这样查询列表

   { testResult: 
      { foo:
         {foo1: x},
         {foo2: y}
      },
      { bar:
         {bar1: z}
let res = this._dbref.database.list('/bmzi-answers',{
      query: {
        orderByKey: true,
        equalTo: id
      }
    })
{{res | async | json}}
显示结果,表明查询是有效的。我得到的是

[{"cat1":3, "cat2":3, "cat3":3, "$key":"cat"}]
如何减少组件逻辑中的值,以获得所有标记为cat*的问题的总和

我理解filter/map/reduce等概念,但我对反应式Javascript、Angular2和AngularFire还不熟悉

请帮助并提前感谢您

编辑: 所有儿童都有cat前缀,这是域/问卷的一部分。此代码

  let res = this.dbRef.database.list(`/bmzi-answers/${id}`)
                  .do((array) => { console.log(JSON.stringify(array)); })
                  .map((array) => array
                      .reduce((acc, element) => acc + element.$value, 0)
            )
  let score = res.subscribe(sum => {
                  console.log("score: " + sum)
              });
  return score;
第一次调用时生成此控制台输出:

[
    { "$key": "cat1", "$value": 3 },
    { "$key": "cat2", "$value": 3 },
    { "$key": "cat3", "$value": 3 }
]
score: [object Object]
第二次是:

[]  
score: undefined  
[{"$value":3,"$key":"fitges1"}]
score: undefined  
[{"$value":3,"$key":"fitges1"},{"$value":3,"$key":"fitges2"}]
score: undefined 
[{"$value":3,"$key":"fitges1"},{"$value":3,"$key":"fitges2"},{"$value":3,"$key":"fitges3"}]  
score: undefined 

您的示例输出显示了以下数据:

{
    "bmzi-answers": {
        "cat": {
            "cat1": 3,
            "cat2": 3,
            "cat3": 3
        }
    }
}
您的查询使用
orderByKey
equalTo
获取可观察到的列表,该列表发出一个数组。如果键存在,查询将只返回包含单个对象的数组。将键合并到查询路径中会更简单,如下所示:

let res = this._dbref.database.list(`/bmzi-answers/${id}`);
此查询返回的可观察对象将是一个包含键的子项的数组(以AngularFire方式表示):

RxJS
map
运算符可用于将发出的数组转换为另一个值,并且可以使用
array.proptype
函数执行转换,您可以使用该函数声明您熟悉:

let id = "cat";
let regExp = new RegExp(`${id}\\d+`);
let res = this._dbref.database
    .list(`/bmzi-answers/${id}`)
    .map((array) => array
        .filter((element) => regExp.test(element.$key))
        .reduce((acc, element) => acc + element.$value, 0)
    );

如果所有子项都有
cat
前缀,则不需要
过滤器,但您的问题无法说明是否存在这种情况。

流会发出数据。一条可观测的河流就是一条小溪

例如:

let stream = Rx.Observable.from([3,6,9]) 
这个代码创建了一个可观察的流,它发出3,然后是6,然后是9

现在让我们假设我们想要将这些值加倍:

let stream = Rx.Observable.from([3,6,9]).map((value) => {return value*2})
现在这条溪流发出6,12,18

最后,我们可以做:

let stream1 = Rx.Observable.from([3,6,9])
let stream2 = stream1.map((value) => {return value*2})
现在我们可以订阅stream1或stream2或两者

PS a
.reduce()
功能也可用,与es5
阵列相同。reduce
功能。您可以对流执行与对数组相同的操作

数组是内存中的序列。流是随时间变化的序列


这就是为什么我们可以轻松地将数组转换为流。我们可以在每个发射之间设置间隔。etc

这几乎解决了问题,但当我订阅res时,
let score=res.subscribe(sum=>console.log(sum))
的值未定义,但仅第一次计算了分数。我如何保证在订阅res时还原完成?reduce是同步的,所以这不是问题所在。如果在
map
操作符之前添加
do((array)=>{console.log(JSON.stringify(array));})
,导致
未定义的
分数的第一个发出的数组值是什么?它是[{“$value”:3,$key”:“fitges1”},{“$value”:3,$key”:“fitges2”},{“$value”:3,$key”:“fitges3”}。我不知道是否合适,但是我会发布一个答案来显示代码。它应该是
console.log(“score:+sum)
score
变量保存subscription对象。这有助于理解“更大的图景”,并提醒我订阅转换后的observable对象非常感谢你,上帝也保佑你!