Обработка нескольких ответов от Promises React Native - PullRequest
2 голосов
/ 08 мая 2020

У меня есть несколько функций, которые возвращают ответы Promise. Теперь я пытаюсь захватить их все и отправить все данные на бэкэнд. Однако я не знаю, как их всех схватить. У меня это вроде:

   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);

}

Но проблема здесь в том, что они все как-то смешаны.

Пример: иногда reponse2 имеет данные всех трех функций, а иногда response3 имеет все необходимые данные, в то время как в response2 отсутствует несколько объектов. Как мне это исправить? Должна ли быть какая-то функция для формирования массива из всех ответов (с проверкой, существует ли элемент) или есть способ? Просто для двойной проверки я добавляю здесь пример функции (другие идентичны):

 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 Вторая функция:

  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 }
                });
            });
        })
    })
}

1 Ответ

3 голосов
/ 08 мая 2020

Основная проблема здесь, в getFunction1Data:

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

Вы устанавливаете состояние на основе существующего состояния. Каждый раз, когда вы это делаете, вам нужно использовать форму обратного вызова setState, а не форму, в которую вы передаете состояние напрямую. Причина в том, что обновления состояния могут быть асинхронными и «группироваться», когда вы вносите несколько изменений между визуализацией. Таким образом, this.state.ActivityItem может быть устаревшим, когда вы создаете новое состояние, которое вы даете setState.

Чтобы использовать форму обратного вызова, вообще не используйте allData и выполните:

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

Отдельная проблема заключается в том, что каждый вызов getFunction1Data возвращает (через обещание) все собранных данных, а не только данные, собранные этим вызовом. Мне не совсем понятно, что вы хотите сделать, но я бы предпочел, чтобы getFunction1Data возвращал только собранные данные (newData), а не все данные, или модифицировал их так, чтобы он получал все информацию, которую вы хотите получить, а не одну треть, так что вы можете вызвать ее только один раз.

...