简体   繁体   中英

Handling multiple responses from Promises React Native

I have a few functions which return Promise responses. I am now trying to grab all of them and send all the data to the backend. However, I don't know how to grab them all. I have it like:

   componentDidMount() {
    Promise.all([
        this.getFunction1Data(ONEDAYINTERVAL), //returns an array of objects
        this.getFunction2Data(ONEDAYINTERVAL),
        this.getFunction3Data(ONEDAYINTERVAL),

    ]).then(([response1, response2, response3]) => {
        this.sendDataToServer(response3);
        // do stuff with your data
    }).catch(e => console.error);

}

But the issue here is, that somehow they're all mixed.

Example: sometimes reponse2 has data from all three functions, and sometimes response3 has all the data needed, while response2 is missing a few objects. How would I fix that? Should there be some function to form an array from all of the responses(with a check if element exists) or there is a way around? Just for the double-check I am adding an example of a function here (others are identical):

 getFunction1Data(dateFrom) {

    return new Promise((resolve) => {
        AppleKit.initKit(KitPermissions.uploadBasicKitData(), (err, results) => {
            if (err) {
                return;
            }

            AppleKit.getSamples(dateFrom, (err, results) => {
                if (err) {
                    return resolve([]);
                }
                const newData = results.map(item => {
                    return { ...item, name: "Item1" };
                });
                const allData = [...this.state.ActivityItem, ...newData];
                this.setState({ ActivityItem: allData });
                resolve(allData);
            });
        })
    })
}

UPDATE Second Function:

  getFucntion2Data(dateFrom) {

    return new Promise((resolve) => {
        AppleKit.initKit(KitPermissions.uploadBasicKitData(), (err, results) => {
            if (err) {
                return;
            }

            AppleHealthKit.getStepsSample(datefrom, (err, results) => {
                if (err) {
                    return resolve([]);
                }
                const newData = results.map(item => {
                    return { ...item, name: "StepsSample" };
                });
                this.setState(({ActivityItem}) => {
                    ActivityItem = [...ActivityItem, ...newData];
                    resolve(ActivityItem);
                    return { newData }
                });
            });
        })
    })
}

The major problem is here in getFunction1Data :

 const allData = [...this.state.ActivityItem, ...newData];
 this.setState({ ActivityItem: allData });

You're setting state based on existing state. Whenever you do that, you need to use the callback form of setState , not the form you pass state to directly. The reason is that state updates may be asynchronous and are "batched" when you make several changes between renders. So this.state.ActivityItem can be out of date when you build the new state you're giving to setState .

To use the callback form, don't have allData at all, and do:

 this.setState(({ActivityItem}) => {
     ActivityItem = [...ActivityItem, ...newData];
     resolve(ActivityItem);
     return { ActivityItem }
 });

The separate problem is that you have each call to getFunction1Data returning (via the promise) all of the gathered data, not just the data gathered by that call. It's not entirely clear to me what you want to do, but I'd lean toward having getFunction1Data return only the data it gathered ( newData ), not all the data, or to modify it so that it gets all of the information you want to get, not just one third of it, so you can call it just once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM