1

Currently I am doing a forEach loop to populate the array based on user's favorites:

usersref.child(formData.openid + '/favorites').once('value', function(snapshot){
  var favlist = [];
  snapshot.forEach(function(fav){
    fav = fav.key();
    ref.child(fav).once('value',function(snapshot){
      favlist.push(snapshot.val());
    });
  });
  response.writeHead(200, {'Content-Type': 'application/javascript'});
  response.write(favlist);
  response.end();
});

usersref is a the database for the user, ref is the database for the items. formData.openid is user's unique id.

Aero Wang
  • 8,382
  • 14
  • 63
  • 99

1 Answers1

1

Since the two lists are disjunct, you'll need a separate read for each item. But to ensure all reads are done before sending the response to the client, you can use promises:

usersref.child(formData.openid + '/favorites').once('value', function(snapshot){
  var promises = [];
  snapshot.forEach(function(fav){
    promises.push(ref.child(fav.key()).once('value'));
  });
  Promise.all(promises).then(function(snapshots) {
    var favlist = snapshots.map(function(snapshot) { return snapshot.val(); });
    response.writeHead(200, {'Content-Type': 'application/javascript'});
    response.write(JSON.stringify(favlist));
    response.end();
  }).catch(function(error) {
    response.status(500).send(error);
  });
});
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • This still requires the server to send multiple request to firebase, say if there are a hundred keys, it needs to request 100 times to just make a new list - which would be really slow. `promises.push(ref.child(fav.key()).once('value')` is semantically incorrect btw. – Aero Wang Aug 15 '17 at 02:05
  • 1
    Thanks for catching the typo - fixed. Requesting a reasonable number of items like this is not slow, since the requests are pipelined over a single connection. See http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786 for more on that. – Frank van Puffelen Aug 15 '17 at 02:28
  • Make sense. Thanks. – Aero Wang Aug 15 '17 at 02:49
  • Actually it doesn't work just yet, I received `(node:47780) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: response.status is not a function (node:47780) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.` and there is no data output... – Aero Wang Aug 15 '17 at 03:00
  • After changing `response.status(500).send(error);` to `response.writeHead(500, {'Content-Type': 'text/html'}); response.write('favlist error: ' + err); response.end();` I now have an output `favlist error: TypeError: First argument must be a string or Buffer` – Aero Wang Aug 15 '17 at 03:04
  • 1
    Looks like the problem is using `response.write(favlist);` where in `response.write()` the argument can only be a string or Buffer - so `response.write(JSON.stringify(favlist))` – Aero Wang Aug 15 '17 at 03:10