-1

I am having an issue within one of my reducers where I have all of the information readily available to return to the front-end except for one array called "items" which I need to do an additional fetch to get more data back. The issue I am having with this fetch is that it ultimate leads to a return of a promise instead of returning the value. My question is how can I get the value instead of the promise? (e.g. via blocking everything else until the promise resolves and then sending that back).

I have commented throughout the below code to hopefully explain everything more clearly:

export const getItemsForHistory = createSelector(
    [getAllHistory, getAllItems, getHistoryPage], (history, items, page) => {
        let itemIds = `[a bunch of ids]`;

        //this is the call I am making to fetch the additional data for "items"
        //this return statement is sending back a promise and not a value
        return getUpdatedItems(itemIds, items).then(result => {
            //result is the actual value I want
            return result;
        }, error => {
            //if the fetch fails, I would like to send a default value for "items"
            //note, if I place this return outside of this entire promise and remove the promise, it works as expected with the default data
            return history.map(h => items.get(h.get('item'), null))
        }).catch(error => {
            return history.map(h => items.get(h.get('item'), null))
        })
    }
)

//I would like for this method to run asychronously
const getUpdatedItems = async (itemIds, items) => {
    let result = await fetchHistoryItemsDetail(itemIds);
    return result;
}

const fetchHistoryItemsDetail = (itemIds) => {
    let headers = {
            "Content-Type": "application/json",
        },
        fetchUrl = `XXXXXXXXX`;
    return fetch(fetchUrl, {
        method: "POST",
        headers: headers,
        body: itemIds,
        withCredentials: true,
        crossDomain: true,
    })
        .then(response => {
            return response.json();
        })
        .catch(error => {
            throw error;
        })
}

export const getSortedHistory = createSelector(
    [getAllHistory, getItemsForHistory, getHistorySort, getHistoryPage], (history, items, sort, page) => {
        //this is where items is ultimately retured to the front end but it is now a promise and not an array of data
        //(from getItemsForHistory)
        return sortedEntities(history, items, sort)
    }
)

I hope that my question is clear, but please let me know if further elaboration is needed.

Kyle Bachan
  • 1,053
  • 2
  • 15
  • 33

1 Answers1

0

You cannot return data from within a promise's cats/error handler

If for both you want to send data, I would suggest wrapping in another promise that will always resolve

return new Promise((res) => {
  //this is the call I am making to fetch the additional data for "items"
  //this return statement is sending back a promise and not a value
  getUpdatedItems(itemIds, items).then(result => {
    //result is the actual value I want
    res(result);
  }, error => {
    //if the fetch fails, I would like to send a default value for "items"
    //note, if I place this return outside of this entire promise and remove the promise, it works as expected with the default data
    res(history.map(h => items.get(h.get('item'), null)));
  }).catch(error => {
    res(history.map(h => items.get(h.get('item'), null)));
  })
});
Naftali
  • 144,921
  • 39
  • 244
  • 303
  • Thank you for your response. But in this scenario, aren't you still returning "items" as a promise? – Kyle Bachan Jul 05 '18 at 20:22
  • But you are also returning from the error states – Naftali Jul 05 '18 at 20:26
  • I think I see what you mean. Ok I will apply this. Thank you. – Kyle Bachan Jul 05 '18 at 20:33
  • 1
    Wrapping in another promise makes no sense at all here. – jfriend00 Jul 06 '18 at 03:25
  • @jfriend00 I am not sure this is a duplicate. Basically the op wants to have the promise resolve even if it fails. I believe he understands how promises work – Naftali Jul 06 '18 at 12:51
  • @Neal - Then, all you do is add a `.catch()` to catch the rejection locally and turned it back into a resolved promise. Your addition of wrapping in another promise is a `promise anti-pattern`. – jfriend00 Jul 06 '18 at 15:49
  • @Neal - The part of the question "My question is how can I get the value instead of the promise?" is the classic duplicate. You can't. The OP does not understand asynchronous code apparently and that duplicate (which is apparently gone now) describes that in great detail. – jfriend00 Jul 06 '18 at 15:53