0

I am having problem with Promise.all function for multiple API calls. I am making multiple api calls and then console.log the result. I am able to see the results when do console.log within the map function, but when trying to set the state in order to render and display in UI, the data is not flowing to state. I don't know where exactly the problem is and why data is not flowing to state.

Here is my code.

    componentDidMount() {
        
        const promises = data.map(id => {
            return new Promise((resolve) => {
              fetch(`https://example.com/api/ITems/${id.ID}`)
                .then(response => {
                  return new Promise(() => {
                    response.json()
                    .then(response => {
                        console.log(response); // this console log is showing me data into console, but the console.log below in promise.all section is not showing any data
                        resolve()
                      })
                      .catch((error) => {
                            console.log(error);
                        })
                  })
                })
            })
          })

        Promise.all(promises).then(results => {
            this.setState({Ids: results.data}); // no data is passing to state
           console.log(results); // this console.log does not work. when remove the console.log in loop, i cannot see anything. data is not flowing here
        })
        .catch((error) => {
            console.log(error);
        })
      }
    

Thanks everyone.

Jennifer
  • 93
  • 6

2 Answers2

1

Its happening because you are resolving as undefined thus all of your promises return value is undefined

Change it to: resolve(response) and that way it will actually resolve using your desired response

    const promises = data.map(id => {
        return new Promise((resolve) => {
          fetch(`https://example.com/api/ITems/${id.ID}?realm=xyz`, { headers })
            .then(response => {
              return new Promise(() => {
                return response.json() // <--------------------------- Additionally you need to return this as well
                .then(response => {
                    console.log(response); // this console log is showing me data into console, but the console.log below in promise.all section is not showing any data
                    resolve(response) // <---------------------------- ISSUE is here
                  })
                  .catch((error) => {
                        console.log(error);
                    })
              })
            })
        })
      })
Rikin
  • 5,351
  • 2
  • 15
  • 22
  • Hi @Rikin. You are right. The array in promise.all section was undefined in console. now data is coming . that console is working. But still have a challenge. Data is still not in state. Promise.all(promises) .then(response => { this.setState({Ids: response.data}); // still no data console.log(response); // this is working . showing data in console }) – Jennifer Nov 18 '20 at 02:13
  • constructor(props) { super(props); this.state = { Ids: [] }; console.log(this.state.Ids); // no data still here } – Jennifer Nov 18 '20 at 02:14
  • @Raza I guess you just need to look at the shape of the object in your console.log and adjust accordingly. May be its `response.data.data`? I cant tell without the shape of how its being logged in console. If you are not sure try `console.log(JSON.stringify(response.data))` and let me know and I'll point you to it. – Rikin Nov 18 '20 at 02:29
  • Thank you so much @Rikin . its working now. the last issue was due to `this.setState({Ids: response.data});` I was concatenating the .data with response. Much Appricated and thanks alot – Jennifer Nov 18 '20 at 02:48
1

You're not resolveing with anything. Consider avoiding the explicit promise construction antipattern, and .catch only in the Promise.all:

const promises = data.map(id => 
  fetch(`https://example.com/api/ITems/${id.ID}?realm=xyz`, { headers })
    .then(res => res.json())
    .then(result => result.data)
 );
Promise.all(promises).then(results => {
  this.setState({Ids: results});
})
.catch((error) => {
  console.log(error);
});

The value Promise.all gets resolved with will always be an array - it won't have a .data property. It sounds like each individual fetch result returns an object with a data property, so you should do that inside the .map as done above, not in the Promise.all.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320