0

I am iterating over an object using a regular for loop and that works fine for me. But, I was trying to remove all for loops of my code in favor of array iteration instead and, for some reason I can't understand why when using forEach I get a different result.

Note: forEach here is from a module called p-iteration

https://www.npmjs.com/package/p-iteration

This works fine, it returns the correct values.

  for await (const [key, value] of Object.entries(tatGroupedByRegion)) {
    onTarget = 0;
    notOnTarget = 0;
    const cases = [];
    await forEach(value, async email => {
      if (!cases.includes(email.new_name)) {
        cases.push(email.new_name);
        isOnTarget(email);
      }
    });

    backlogData[key].tatd1 = percentage(onTarget, notOnTarget);
    tatd1Total.value += parseInt(percentage(onTarget, notOnTarget), 10);
    if ((parseInt(percentage(onTarget, notOnTarget) !== 0), 10)) {
      tatd1Total.count += 1;
    }
  }

This does not work,this part here backlogData[key].tatd1 = percentage(onTarget, notOnTarget), returns the same value over and over.

 await forEach(Object.entries(tatGroupedByRegion), async ([key, value]) => {
    onTarget = 0;
    notOnTarget = 0;
    const cases = [];
    await forEach(value, async email => {
      if (!cases.includes(email.new_name)) {
        cases.push(email.new_name);
        isOnTarget(email);
      }
    });

    backlogData[key].tatd1 = percentage(onTarget, notOnTarget);
    tatd1Total.value += parseInt(percentage(onTarget, notOnTarget), 10);
    if ((parseInt(percentage(onTarget, notOnTarget) !== 0), 10)) {
      tatd1Total.count += 1;
    }
  });
Adrian Sultu
  • 330
  • 5
  • 16
  • check this link : https://stackoverflow.com/questions/50844095/should-one-use-for-of-or-foreach-when-iterating-through-an-array – Mohammad Yaser Ahmadi Feb 17 '21 at 15:23
  • [k.meinkopf's answer](https://stackoverflow.com/a/66244990/) shows the source code. [The documentation](https://toniov.github.io/p-iteration/global.html#forEach) mentions the same thing - `forEach` works with *arrays*. `Object.entries` returns an *iterable*, so it doesn't work with the assumption that only array(-likes) will be passed in. You either need to convert the entries to an array first or you need to straight up use the iterable itself without materialising it. I'm not really sure how, as I'm not sure why you have `async`/`await` - it doesn't seem like you have async operations. – VLAZ Feb 17 '21 at 16:13

1 Answers1

0
exports.forEach = async (array, callback, thisArg) => {
  const promiseArray = [];
  for (let i = 0; i < array.length; i++) {
    if (i in array) {
      const p = Promise.resolve(array[i]).then((currentValue) => {
        return callback.call(thisArg || this, currentValue, i, array);
      });
      promiseArray.push(p);
    }
  }
  await Promise.all(promiseArray);
};

This is the implementation of forEach that you're using. The callback receives this as the first argument, this can be a problem.

k.meinkopf
  • 158
  • 6
  • "*it uses `for .. in` instead of `for .. of`*" it uses a normal `for` loop and it uses the `in` operator. That's not the same as `for...in`. However, the `for` loop does mean that it only works on array-likes which `Object.entries` is not. – VLAZ Feb 17 '21 at 16:06
  • @VLAZ thanks for this clarification, I can't understand why I thought about `for .. in`. – k.meinkopf Feb 17 '21 at 16:38