javascript - ReactJS how to wait for all API calls to be ended in componentDidMount of simple component - Stack Overflow

I'm using latest react and very basic app which calls 3rd party service API which actually is not

I'm using latest react and very basic app which calls 3rd party service API which actually is not well designed in meaning of following. I have to execute one call which return list and then have to iterate and call other end point to get data for item from list and then again in data have new list for which I have to call 3rd API end point. After I receive all data I bined it to one items array and place it in state in ponentDidMount function but this final step works only if I surround it with setTimeout.

Is there some elegant way to do that?

I'm using fetch and really pure react ponents, have my own simple service from where I call API, here is some code parts...

    items[tag].sensors = [];
    API.getObjects(sessionData, userDetails, tag).then(links => {

    Object.keys(links.link).forEach(link => {
        API.getObjects(sessionData, userDetails, link).then(objLink => {
            Object.keys(objLink.link).forEach(function (key) {
                let obj = objLink.link[key];
                if (obj && obj.type === 'sensor') {
                    API.getSensorNames(sessionData, key).then(response => {
                        const sensor =  response.sensor;
                        // some sensor calculations....
                        items[tag].sensors.push(sensor);
                    });
                }
            });
        });
    });
});
// this part only works if it's surrounded with timeout
setTimeout(function() {
    let processedItems = [];
    for (var key in items) {
        if (items.hasOwnProperty(key)) {
            processedItems.push(items[key]);
        }
    }
    self.setState({
        items: processedItems
    });

}, 1000);

Thanks in advance.

I'm using latest react and very basic app which calls 3rd party service API which actually is not well designed in meaning of following. I have to execute one call which return list and then have to iterate and call other end point to get data for item from list and then again in data have new list for which I have to call 3rd API end point. After I receive all data I bined it to one items array and place it in state in ponentDidMount function but this final step works only if I surround it with setTimeout.

Is there some elegant way to do that?

I'm using fetch and really pure react ponents, have my own simple service from where I call API, here is some code parts...

    items[tag].sensors = [];
    API.getObjects(sessionData, userDetails, tag).then(links => {

    Object.keys(links.link).forEach(link => {
        API.getObjects(sessionData, userDetails, link).then(objLink => {
            Object.keys(objLink.link).forEach(function (key) {
                let obj = objLink.link[key];
                if (obj && obj.type === 'sensor') {
                    API.getSensorNames(sessionData, key).then(response => {
                        const sensor =  response.sensor;
                        // some sensor calculations....
                        items[tag].sensors.push(sensor);
                    });
                }
            });
        });
    });
});
// this part only works if it's surrounded with timeout
setTimeout(function() {
    let processedItems = [];
    for (var key in items) {
        if (items.hasOwnProperty(key)) {
            processedItems.push(items[key]);
        }
    }
    self.setState({
        items: processedItems
    });

}, 1000);

Thanks in advance.

Share Improve this question asked Feb 4, 2018 at 0:57 vaskevaske 9,56211 gold badges52 silver badges70 bronze badges 2
  • You're looking for Promise.all(). – SLaks Commented Feb 4, 2018 at 0:58
  • @SLaks yeah right, tnx – vaske Commented Feb 4, 2018 at 9:20
Add a ment  | 

2 Answers 2

Reset to default 3

What about using async/await operators.

These operators allows you to wait until the response is ready.
You can use this kind of helper function.

getItems = async (...) => {
  ...
  items[tag].sensors = []
  const links = await API.getObjects(sessionData, userDetails, tag)

  Object.keys(links.link).forEach(async (link) => {
    const objLink = await API.getObjects(sessionData, userDetails, link)

    Object.keys(objLink.link).forEach(async (key) => {
      let obj = objLink.link[key]
      if (obj && obj.type === 'sensor') {
        const response = await API.getSensorNames(sessionData, key)
        const sensor = response.sensor
        items[tag].sensors.push(sensor)
      }
    })
  })

  this.setState({ items })
}

Also you can see this great documentation.

Simply, You can use Promise to wait until you get values from the API call, therefore you will put your code in function like this

function prepareItems() {
  items[tag].sensors = [];
  return new Promise((resolve, reject) => {
    API.getObjects(sessionData, userDetails, tag).then(links => {
      Object.keys(links.link).forEach(link => {
        API.getObjects(sessionData, userDetails, link).then(objLink => {
          Object.keys(objLink.link).forEach(function(key) {
            let obj = objLink.link[key];
            if (obj && obj.type === "sensor") {
              API.getSensorNames(sessionData, key).then(response => {
                const sensor = response.sensor;
                // some sensor calculations....
                items[tag].sensors.push(sensor);
                // whenever you set resolve it will end the promise
                //and pass the result it to the then function
                resolve(items)
              });
            }
          });
        });
      });
    });
  });
}

and use then to get the result from the prepareItems function after its resolved

prepareItems().then(items => {
//Do what ever you want with prepared item
})

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745390312a4625631.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信