-1

I want to return objects with a custom shape from promise.allSettled

let fns = [
  { fn: fn1, name: "myName1" },
  { fn: fn2, name: "myName2" },
];

const allData = await Promise.allSettled(
  fns.map((entry) =>
    entry.fn
      .then((res) => ({
        name: entry.name,
        status: "fulfilled",
        res: res.Data,
      }))
      .catch((err) => ({
        name: entry.name,
        status: "rejected",
        res: undefined,
      }))
  )
);

upon looping over this list, I only have status and reason available. Is it possible to return custom objects like this?

Phil
  • 157,677
  • 23
  • 242
  • 245
user38643
  • 341
  • 1
  • 7
  • 2
    Since you're re-resolving rejected promises in the array, just change `Promise.allSettled` to `Promise.all` – Patrick Roberts Dec 08 '22 at 01:11
  • I want to evaluate which promises fail and succeed. Promise.all will reject if any promise rejects whereas promise.allsettled will wait to get results from all the promises irrespective of their response status. – user38643 Dec 08 '22 at 01:13
  • 3
    I'm aware of what `Promise.allSettled` does, however, you've explicitly chained `.catch` on each promise which means that none of them can reject, and you are already resolving them with objects that indicate their status. Thus my suggestion to use `Promise.all` instead since you've essentially implemented what `Promise.allSettled` does. – Patrick Roberts Dec 08 '22 at 01:15
  • 1
    `Promise.any` or `Promise.allSettled`? Your title probably needs correction – Phil Dec 08 '22 at 01:17
  • What is `entry.fn`? If it's a function, you need to call it with `entry.fn()` – Barmar Dec 08 '22 at 01:27
  • @Phil That's what the loop expects, but from the name I suspect it's actually a function that returns a promise. – Barmar Dec 08 '22 at 01:29
  • There's no code that creates a `reason` property. I don't see any way that you could be getting that in the result. – Barmar Dec 08 '22 at 01:30
  • It's unclear what you're asking or how you're observing the result (ie _"I only have `status` and `reason`"_). Are you aware of the [data types that `Promise.allSettled()` resolves with](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled#return_value)? – Phil Dec 08 '22 at 01:31
  • Have a look at [this](https://stackoverflow.com/a/74338549/1048572). (Seems close to be a duplicate question even) – Bergi Dec 08 '22 at 03:04

2 Answers2

0

This was mentioned in the comments above but I'll elaborate...

Promise.allSettled() is used to resolve a list of promises, whether they succeed or fail. It provides you a list of results shaped either like

export interface PromiseResolution<T> {
    status: 'fulfilled';
    value: T;
}

or

export interface PromiseRejection<E> {
    status: 'rejected';
    reason: E;
}

(DefinitelyTyped source)

Since you are manually handling rejection, all your promises resolve successfully so you don't need the features that allSettled() offers.

Instead, simply use Promise.all().

const allData = await Promise.all(
  fns.map(({ fn, name }) =>
    fn
      .then(({ Data }) => ({
        name,
        status: "fulfilled",
        res: Data,
      }))
      .catch(() => ({
        name,
        status: "rejected",
      }))
  )
);

Also, if fn1 and fn2 are promises, they're poorly named. If they're functions, you should be calling them.

Phil
  • 157,677
  • 23
  • 242
  • 245
0

I think your code is some kind of strange.

When you track the code:

  1. Promise.allSettled() takes an array generated from the map method
  2. The array generated from the map method in fact contains objects and not promises, and that's because you resolve the promises already in that map method, so the values inside the array passed to Promise.allSettled() are just objects.
  3. And when the Promise.allSettled() takes inside its array any value that's not a promise, it consider that value as a resolved promise already and will put that value in the array of results that you can get in the .then() handler.
  4. So the results array will contains its normal objects with a resolved promises each value will be the object passed to it, and all status is fulfilled

So, you can imagine that your Promise.allSettled() takes an array like that:

let allData = Promise.allSettled([
    { name: "myName1", status: "fulfilled", res: "" },
    { name: "myName2", status: "fulfilled", res: "" }
])

So, it will consider the two objects as a resolved promises, then if you handle that promise like that:

allData.then((results) => {
    console.log( results )
})

You will find this result:

[
    {status: "fulfilled",  value: { name: "myName1", status: "fulfilled", res: "" }},
    {status: "fulfilled",  value: { name: "myName2", status: "fulfilled", res: "" }}
]

Now I think it's clear to you, what your code is ready does.

Let's come to the main question,

Can I handle the object returned in the array of result in the Promise.allSettled()

And the answer is No for sorry, because this is something in the builtin structure of Promise.allSettled() that it works with.

But you can structure the object in the value of the object that returned by the Promise.allSettled()

I hope I helped you understand that.