javascriptlogical-operatorskinvey

JS logical issues in condition


I am building a chat application with Kinvey mbaas as database. I have a collection storing chats with the following data columns: _id, firstUser, otherUsers, history. So far the idea is: when a message is posted GET is requested to find if there is chat between the two users. GET takes the whole collection and iterates over entries and checks if firstUser and otherUsers match. This is where the problem comes: they don't match ever. Code bellow:

for (let entity = 0; entity < response.length; entity++) {
console.log('DEV_firstUser: ' 
                 + response[entity]['firstUser'] + '|' + firstUser);
    console.log('DEV_otherUsers: |' 
                 + response[entity]['otherUsers'] + '|' + otherUsers + "|");

    console.log(response[entity]['firstUser'] === firstUser);
    console.log(response[entity]['otherUsers'] === otherUsers);
    // The problematic condition - the logs above are demonstrations.
    if (response[entity]['firstUser'] === firstUser 
            && response[entity]['otherUsers'] === otherUsers) {
                id = response[entity]['_id'];
                console.log('DEV_id: ' + id);
                index = entity;
                console.log(response[index][id]);
            }
    }

'response' is the collection - array of objects from what I can see. 'entity' is straightforward - each entity inside the collection. 'otherUsers' is array.

This is what I get on the console:

DEV_firstUser: alex|alex
DEV_otherUsers:|Ganka|Ganka|
true
false

Solution

  • There are two issues with your code (disclaimer: answer is based on the original version of the question).

    firstUser comparison

    console.log('DEV_firstUserComparison: ' 
        + response[entity]['firstUser'] == firstUser);
    

    yields false, because + has a higher precedence than == or ===, so you're actually comparing a string to a user object (note how you also don't see your "DEV_firstUserComparison:" in the output).

    Instead, put the comparison in brackets:

    console.log('DEV_firstUserComparison: ' 
            + (response[entity]['firstUser'] == firstUser));
    

    Short snippet to demonstrate the issue:

    console.log('foo' === 'foo');      //true
    console.log('f' + 'oo' === 'foo'); //true

    otherUsers comparison

    Even after fixing the first issue

    console.log('DEV_otherUsersComparison: ' 
        + (response[entity]['otherUsers'] == otherUsers));
    

    still returns false. This is due to the fact that otherUsers is an array and you cannot simply compare those with ==.

    Instead, you have a few other options. See the following questions on Stack Overflow for details:

    Basically: either write your own comparison method or convert both arrays to string before comparing (which will not work when the elements are ordered differently).

    The easiest way for your use case would probably be:

    response[entity]['otherUsers'].length == otherUsers.length
      && response[entity]['otherUsers'].every(function(v, i) { return v == otherUsers[i]})
    

    Again, a short snippet to demonstrate:

    var array1 = ['foo', 'bar'];
    var array2 = ['foo', 'bar'];
    
    function eq(a1, a2) {
      return a1.length == a2.length && a1.every(function(v, i) {
        return v === a2[i]
      });
    }
    
    console.log(array1 == array2);   //false
    console.log(eq(array1, array2)); //true