16

I am trying to determine whether or not an array holds a certain item. If it does, I would like to hold the function, otherwise it should get added.

function addPacking(item){

    data.packings.forEach(function(entry){
       if(item.name == entry.name){
           return;
       }
    });

    data.packings.push(item);

}

Unfortunately, the data is pushed even when the if condition is met. How do I prevent this behaviour without using an else condition?

(I do not want to use else because my actual code is a lot more complex than this and I'd like to keep it readable)

Edit:

Does forEach execute asynchronously?

user2422960
  • 1,476
  • 6
  • 16
  • 28

5 Answers5

21

Old ways are sometimes the best. It's because you're passing a delegate function when calling .forEach. The return within the delegate is getting lost, and isn't applying to anything. To get your desired result, you'll want to exit the calling function addPacking. This can be done using a simply for loop.

function addPacking(item){
    for (var i = 0; i < data.packings.length++; i++) {
        if (item.name == data.packings[i].name) {
            return;
        }
    }

    data.packings.push(item);
});

This approach also supports older browsers, unlike some, every and forEach

Richard
  • 8,110
  • 3
  • 36
  • 59
  • It works but an array may also contains undefined (of course this may not be an issue for OP case). – Adriano Repetti Jul 25 '14 at 09:22
  • That's correct Adriano, I'm just basing my conditions on those provided. :) – Richard Jul 25 '14 at 09:25
  • I found that this is the most convenient option, thank you and all others for providing so many different methods and explanations! – user2422960 Jul 25 '14 at 09:32
  • It worked. thank you :). We can also try this way ** function addPacking(item){ for (let record of data.packings) { if (item.name == record.name) { return; } } data.packings.push(item); }); ** – Bandham Manikanta Jan 21 '21 at 16:14
  • This is such a crazy error. I saw my code was executing in both "blocks" and remembered something about this before. Thanks! – Benjamin Hobson Jun 24 '23 at 15:01
7

You can't stop forEach execution other than throwing an exception (@Yoshi). Which should not be considered as an option to affect program code flow (@Me).

What you can do is to use another method some or every

function addPacking(item){
    var contains = data.packings.every(function(entry){
       return item.name != entry.name;
    });

    if(contains) {
       data.packings.push(item);
    }
}

Or

function addPacking(item){
    var conatins = !data.packings.some(function(entry){
       return item.name == entry.name;
    });

    if(contains) { 
       data.packings.push(item);
    }
}
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
3

OLD question but in case someone else comes across this thread.

If you are using ECMAScript 6 you can use the Array find() method

var found = myArray.find(function (element) { return element === arrayToFind; });

so for this particular scenario would be:

function addPacking(item){
    var foundItem = data.find(function(entry){ return entry.name == item.name});
    if (foundItem) data.packings.push(foundItem);    
}

see http://www.w3schools.com/jsref/jsref_find.asp for another worked example.

BtnMike
  • 323
  • 4
  • 6
2

Yo are just returning from the child function but not from the parent function

function addPacking(item){
    var check=false;
    data.packings.forEach(function(entry){
       if(item.name == entry.name){
          check=true; 
          return;
       }
    });
     if (check) return;
    data.packings.push(item);

}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Srinath Mandava
  • 3,384
  • 2
  • 24
  • 37
  • 5
    That will work, but it will still loop through all the items even when a match is found, and the `return` inside the loop is pointless. – Guffa Jul 25 '14 at 09:24
2

Return just aborts the function called in forEach, not your addPackings function.

function addPacking(item){
    var isInPackings = false;
    data.packings.forEach(function(entry){
       if(item.name == entry.name){
           isInPackings = true;
       }
    });
    if (!isInPackings)
        data.packings.push(item);

}
Florian Gl
  • 5,984
  • 2
  • 17
  • 30