0

From Firebase Cloud Functions I do query in Firebase Realtime DB like this:

let logs = this.firebase.database()
.ref('logs')
.orderByChild("userId").equalTo(userId)
.once('value');

Returned data:

{
  "id1abc": {
    "myValue": 1,
    "userId": "abc"
  },
  "id2abc": {
    "myValue": 2,
    "userId": "abc"
  },
  "id3abc": {
    "myValue": 3,
    "userId": "abc"
  }
}

Query returns a couple entries which values which I would like to sum:

let loggedVal = 0;
logs.forEach(log => {
    loggedVal += log.val().myValue;
});
return loggedVal;

Arrow function inside forEach gives me proper value in this case (Sum equals 6).

But when I remove parenthesis like here:

let loggedVal = 0;
logs.forEach(log => loggedVal += log.val().myValue);
return loggedVal;

Returned value isn't sum, but just value from the first element which I'm iterating over (loggedVal == 6). Can anyone explain where does the difference come from?

Doug Stevenson
  • 236,239
  • 27
  • 275
  • 302
froger_mcs
  • 13,632
  • 5
  • 21
  • 34
  • 1
    How can you use `forEach` in an `Object` in the first place? The returned data you showed to us is not an `Array` eligible to `Array.forEach`. – Orelsanpls Oct 19 '17 at 09:12

3 Answers3

3

As per the firbase forEach docs,

You can cancel the enumeration at any point by having your forEach callback function return true.

Here in your second case,

logs.forEach(log => loggedVal += log.val().myValue);

You are returning some value in your first iteration (because you are not using parenthesis), which is considered true. Therefore it stops further iteration, hence you do not get sum but first value.

Prakash Sharma
  • 11,610
  • 3
  • 24
  • 33
  • 1
    I knew that it will be something in javascript basics! Just couldn't find a proper question to ask. Thank you! – froger_mcs Oct 19 '17 at 12:13
1

you misunderstand about the arrow function format.

the 1st one:

let loggedVal = 0;
logs.forEach(log => {
  loggedVal += log.val().myValue;
 });
 return loggedVal;

it's equal to ES5:

let loggedVal = 0;
logs.forEach(function(log){
  loggedVal += log.val().myValue;
 });

 return loggedVal;

but the 2nd one:

 let loggedVal = 0;
 logs.forEach(log => loggedVal += log.val().myValue);
 return loggedVal;

it's equal to in ES5:

 let loggedVal = 0;
 logs.forEach(function(log){
    return loggedVal += log.val().myValue);
 }); 
 return loggedVal;

arrow function => abc() mean { return abc()}, but => { abc } it means {abc(); return;}.

an as the document of firebase :

You can cancel the enumeration at any point by having your forEach callback function return true.

at the first item: return loggedVal += log.val().myValue); // === true, so that it stopped your recursive .forEach.

p.s: Someone also misunderstand => { abc } equals to { return { abc :abc} }

Kai
  • 1,744
  • 15
  • 25
0

Here it's what it should look like

const logs = {
  id1abc: {
    myValue: 1,
    userId: 'abc',
  },
  id2abc: {
    myValue: 2,
    userId: 'abc',
  },
  id3abc: {
    myValue: 3,
    userId: 'abc',
  },
};

Object.keys(logs).reduce((tmp, x) => tmp + logs[x].myValue, 0);
Orelsanpls
  • 18,380
  • 4
  • 31
  • 54