2

I'm trying to use a for each loop to check if a user's ID is in a blacklist group I created. When I try to iterate over the string array of userID's, it says blacklisted.forEach is not a function. Why is that?

  query = { messageTrackingId: req.query.messageId };
    messageId = true;
    Messages.find(query)
      .populate("creator", "username")
      .then(documents => {
        console.log("documents is");
        console.log(documents[0].creatorId);
        let otherUser;
        if (documents[0].creatorId === req.query.creatorId) {
          console.log("ITS A MATCH!")
          otherUser = documents[0].recipientId;
        }
        else if (documents[0].recipientId === req.query.creatorId) {
          console.log("ITS not a match!")
          otherUser = documents[0].creatorId;
        }

        let blacklisted = false;
        User.find({ _id: otherUser }).select("blacklistGroup").then((res) => {

          blacklisted = res[0].blacklistGroup;
          console.log("BLACKLIST SERVER RESPONSE");
          console.log(blacklisted);

          blacklisted.forEach(function(entry) {
            console.log(entry);
        });

CONSOLE OUTPUT

documents is
5e52cca7180a7605ac94648f
ITS not a match!
BLACKLIST SERVER RESPONSE
[ '5e52e8af484eba456ca9e814',
  '5e52f2cc673de71f60019c76',
  '5e52f316673de71f60019c77' ]
(node:12992) UnhandledPromiseRejectionWarning: TypeError: blacklisted.forEach is not a function

Dan O
  • 6,022
  • 2
  • 32
  • 50
user6680
  • 79
  • 6
  • 34
  • 78
  • 1
    You're sure it's an array? Try checking `Array.isArray(blacklisted)` and `typeof blacklisted` – CertainPerformance Feb 23 '20 at 22:02
  • It says Object. but the response looks like a string array. How can I convert it so that I can iterate over it? I don't think I can just JSON.stringify it since it would be more string than array. – user6680 Feb 23 '20 at 22:05
  • Object is better than string, at least. Arrays *are* objects. What does `Array.isArray` show? – CertainPerformance Feb 23 '20 at 22:06
  • ```Array.isArray``` returns false – user6680 Feb 23 '20 at 22:09
  • That's interesting. So it's an object (as arrays are), and is being logged with `[` delimiters as if it's an array, but it's not. One could probably find a workaround by examining the object to find which properties hold the values you want (maybe try accessing `[0]`, `[1]`, etc), but it would be better to fix how the `blacklistGroup` object is being formed, since apparently it's not being formed as a plain array. Unfortunately, I don't know Mongoose – CertainPerformance Feb 23 '20 at 22:13
  • .select in mongoose query above only pulls that field from query nothing else. In original post I have ``` blacklisted = res[0].blacklistGroup;``` if I make it ``` blacklisted = res``` then it outputs like this BLACKLIST SERVER RESPONSE ```[ { blacklistGroup: [ '5e52e8af484eba456ca9e814', '5e52f2cc673de71f60019c76', '5e52f316673de71f60019c77' ], _id: 5e52cca7180a7605ac94648f } ]``` notice the _id field. That's why I drilled down farther with ```res[0].blacklistGroup;``` – user6680 Feb 23 '20 at 22:16
  • @user6680 If you use `Object.entries(blacklisted).foreach` ? – Marios Nikolaou Feb 23 '20 at 22:21
  • @user6680 Are absolutely sure that this is the actual code that produces that console output? Is the `blacklisted.forEach` _inside_ of the `.then((res) => {...` callback? (The closing bracket of that callback is not shown in the code you posted.) It sounds like an [asynchronous issue](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call). – Ivar Feb 23 '20 at 22:23
  • Yes. I'm trying to loop response blacklist group inside .then so that I can send back the appropriate response to user. – user6680 Feb 23 '20 at 22:24
  • Would it be efficient to JSON.stringify the response and then look for a substring matching ```req.query.creatorId``` (The user making the GET request's ID) Keep in mind, blacklist might be more than 3 users lol. It could be 30+ at some point for some users – user6680 Feb 23 '20 at 23:07

3 Answers3

1

I'm not sure why it would display as an array if it's an object, but have you tried creating a new array from it and iterating over that? For example:

blacklisted = [...res[0].blacklistGroup];
blacklisted.forEach(function(entry) {
    console.log(entry);
});
Ed Lucas
  • 5,955
  • 4
  • 30
  • 42
  • I added your code, but it outputs ``` UnhandledPromiseRejectionWarning: TypeError: res[0].blacklistGroup is not iterable```. – user6680 Feb 24 '20 at 02:50
  • Not what I was expecting, but that makes some sense. – Ed Lucas Feb 24 '20 at 04:30
  • Do you think it would be efficient to stringify the data and then look for substrings matching userId? There could be times when that list could be over 100 users for some people, but who knows. Would there be performance concerns with doing that? – user6680 Feb 24 '20 at 15:45
  • It certainly seems like there aught to be an easier way for you to access the data returned. – Ed Lucas Feb 24 '20 at 22:02
1

Is you "User" statement acting like a fetch? If so, you may have to convert your response to json before using it. Something like...

User.find({ _id: otherUser }).select("blacklistGroup")
    .then(res => res.json()) 
    .then(json => {
        blacklisted = json.blacklistGroup;
        console.log("BLACKLIST SERVER RESPONSE");
        console.log(blacklisted);
    });
});
Ed Lucas
  • 5,955
  • 4
  • 30
  • 42
  • That outputted ```TypeError: res.json is not a function``` Here's an example that will give you an idea of an unmodified output. Notice how it has ```_id``` in there too. https://pastebin.com/D0ZEB9AG – user6680 Feb 25 '20 at 01:40
0

I realized that for some reason when I console.log(res[0].blacklistGroup) it was returning

[ '5e52e8af484eba456ca9e814',
  '5e52f2cc673de71f60019c76',
  '5e52f316673de71f60019c77' ]

which is also return type Object. So to solve this, I did the following:


let MyBlacklist = JSON.stringify(res[0].blacklistGroup);
MyBlacklist = JSON.parse(MyBlacklist);

then I was able to loop through

          let counter = 0;
          for (let i = 0; i < MyBlacklist.length; i++) {
            counter++;
            console.log(MyBlacklist[i]);
            console.log(counter);

          }

OUTPUT:

5e52e8af484eba456ca9e814
1
5e52f2cc673de71f60019c76
2
5e52f316673de71f60019c77
3

user6680
  • 79
  • 6
  • 34
  • 78