admin管理员组

文章数量:1401673

I have an array of objects and I have to add one property on each of the objects ing from and async function

I am doing an Array.reduce to iterate on each of the elements and return just one result: One array of objects with the new property.

I have this

const res = await resultOne.reduce(async (users = [], user, i) => {
          let userName;
          try {
            let { name } = await names.getNames(user.id);
            userName = name;
          } catch (error) {
            throw error;
          }
          delete user.id;
          users.push({ ...user, userName });
          return users;
      }, []);

But I get the message

Push is not a function of users

And this is because I think is a promise.

How can I handle async requests in a reduce or a map

I have an array of objects and I have to add one property on each of the objects ing from and async function

I am doing an Array.reduce to iterate on each of the elements and return just one result: One array of objects with the new property.

I have this

const res = await resultOne.reduce(async (users = [], user, i) => {
          let userName;
          try {
            let { name } = await names.getNames(user.id);
            userName = name;
          } catch (error) {
            throw error;
          }
          delete user.id;
          users.push({ ...user, userName });
          return users;
      }, []);

But I get the message

Push is not a function of users

And this is because I think is a promise.

How can I handle async requests in a reduce or a map

Share Improve this question edited Aug 14, 2019 at 20:20 Heretic Monkey 12.1k7 gold badges61 silver badges131 bronze badges asked Aug 14, 2019 at 19:49 Ruben SaucedoRuben Saucedo 2492 silver badges14 bronze badges 2
  • 1 If you can use a Promise library, you can use bluebird's Promise.reduce for this. I.E. const res = await Promise.reduce( resultOne, async (users .... – Paul Commented Aug 14, 2019 at 20:06
  • @Paulpro thank you for your response, the thing is that i don't think that add another dependency is pletely necessary for this case, this is something that I won't be repeating in the whole project. – Ruben Saucedo Commented Aug 14, 2019 at 22:08
Add a ment  | 

2 Answers 2

Reset to default 8

Yes, users is a promise. Don't use reduce with async functions. You could do something like await users in the first line, but that would be pretty inefficient and unidiomatic.

Use a plain loop:

const users = [];
for (const user of resultOne) {
    const { name } = await names.getNames(user.id);
    delete user.id;
    users.push({ ...user, userName: user });
}

or, in your case where you can do everything concurrently and create an array anyway, the map function together with Promise.all:

const users = await Promise.all(resultOne.map(async user => {
    const { name } = await names.getNames(user.id);
    delete user.id;
    return { ...user, userName: user };
}));

Because it's an async function, every time you return something it gets wrapped in a promise. To fix this you need to set the starting array as a promise and then await for the accumulator on each iteration.

const res = await resultOne.reduce(async (users, user, i) => {
  try {
    return [
      ...await users,
      { ...user, userName: await names.getNames(user.id.name) }
    ]
  } catch (error) {
    console.log(error)
  }
}, Promise.resolve([]));

本文标签: javascriptAsync reduce returning promisesStack Overflow