Break out of forEach loop as soon as null is encountered

I have the following JSFiddle. I want to break out of the loop as soon as a null value is encountered. Basically, as soon as it prints Some of the values are null. However, it keeps on printing until it finishes iterating whole array.

Is there a way I can break out of the loop as soon as I encounter null or is there a better way of doing this?

forEach is not made for breaking out of it. Even if it is possible using try/catch I wouldn’t recommend it.
Use for…in instead

Also you have two nested loops. So you need some kind of flag which tells the outer loop that the inner loop breaked.

this should work

for(const data of sourceData)
{
    let allGood = true;
    for (let key in data)
    {
         if(data[key] != null )
         {
             console.log("All good: " + key)
         }
         else 
         {
             console.log("Not good: " + key);
             allGood = false;
             break;
         }
    }
    if(!allGood)
        break;
}
2 Likes

JavaScript has some and every methods on arrays. Here is it every that is wanted, so that you can tell if everything is all good. I just thought of a different better way, but first with every.

Here is the updated code that uses the some method:

const hasNull = data.some(function (item) {
    for (let key in item) {
        if (item[key] !== null ) {
            return true;
        }
    }
});
console.log(hasNull ? "Some of the values are null": "All good");

With data.some(), it checks data[0] and data[1]. If data[0] fails the test, then it doesn’t even bother checking data[1]

But, we can also replace the internals with a some method. I use some here, because it only takes one example of a null to result in things being false.

const isNull = (val) => val === null;
const hasNull = data.some(function (item) {
    return Object.values(item).some(isNull);
});
console.log(hasNull ? "Some of the values are null": "All good");

Similarly with Object.values(item).some(), it checks each property value one by one and as soon as it finds a null value it stops checking.

3 Likes

Hi Paul,

as your solution is very good of course (and maybe the best) I wonder if it makes sense to move a beginner always to a complete other solution?
I am not sure if this won’t make it harder for them to learn?

That’s why I started of with just the single some loop around the internal for loop, so that they have familiarity with what there was before. They can just stay with that if they like. It’s entirely up to them how they feel about progressing from there too.

Hi Paul,

Thanks for your answer. That worked well for finding out Null which stops checking as soon as null is encountered.

I want to adjust your code to do something different.

For example, if I have the following data:

const sourceData = [
  {
    "filename": "deletetestOne.js",
    "answer1": "Y",
    "answer2": "N",
    "riskLevel1": "2",
    "description": ""
  },
  {
    "filename": "deletetestThird.js",
    "answer1": "N",
    "answer2": "N",
    "riskLevel1": "1",
    "description": ""
  }
]

Since null possibility has been ruled out based on your previous solution, I want to run specific checks on answer1 to figure out if they contain Y or not. If it contains Y, then it stops checking.

I was attempting something based on Thallius answer in this fiddle https://jsfiddle.net/s0tc6qnk/7/ but that’s not what I’m looking for and I couldn’t think what should I modify based on your code.

Let me know if I can answer any questions.

I believe this is what I was looking for:

Sorry ahead if this is confusing.

I was looking at Ramda’s approach with propEq for inspiration, and here is a more general function you could use as a predicate.

const propEquals = function(key, prop) {
  // returns inner function
  return function(obj) {
    return obj[key] === prop
  }
}

// could be used like this
sourceData.some(propEquals('answer1', 'Y'))

// or
const answer2isN = propEquals('answer2', 'N')
sourceData.some(answer2isN)

Note: with arrow functions propEquals could be written as

const propEquals = (key, prop) => (obj) => obj[key] === prop

When propEquals is called e.g. propEquals('answer1', 'Y') it returns the inner function with key and prop set to those values. e.g.

function(obj) {
  return obj['answer1'] === 'Y'
}

This will be the function that is passed to some.

Thank you, @rpg_digital !

1 Like

You are welcome.

Of course as per your answer, this might have been easier.

sourceData.some(obj => obj['answer1'] === 'Y')

It’s good to play with some ideas though :slight_smile:

2 Likes