Home > Enterprise >  Returning custom objects from Promise.any
Returning custom objects from Promise.any

Time:12-08

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?

CodePudding user response:

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.

CodePudding user response:

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.

  • Related