Каков лучший / правильный способ использования Promise.all с React-Redux-Thunk? - PullRequest
2 голосов
/ 11 октября 2019
export const FETCH_DB_BEGIN = 'FETCH_DB_BEGIN'
export const FETCH_DB_SUCCESS = 'FETCH_DB_SUCCESS'
export const FETCH_DB_FAILURE = 'FETCH_DB_FAILURE'

export const fetchDatabase = () => {
    return dispatch => {
        const profile_url = 'localhost:5000/profiles'
        const release_url = 'localhost:5000/releases'
        const emp_url = 'localhost:5000/users'
        let promises = []

        let options = {
            headers: header,
            method: 'get',
            mode: 'cors',
            body: null,
        }
        dispatch(fetchDbBegin());

        // run the script async. change state when it's done.
        let profile_promise = new Promise((resolve, reject) => {
            fetch(profile_url, options)
                .then(res => res.json())
                .then(resText => {
                    // Use Dispatch Here?
                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(profile_promise)

        // run the script async. change state when it's done.
        let release_promise = new Promise((resolve, reject) => {
            fetch(release_url, options)
                .then(res => res.json())
                .then(resText => {
                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(release_promise)

        // run the script async. change state when it's done.
        let emp_promise = new Promise((resolve, reject) => {
            fetch(emp_url, options)
                .then(res => res.json())
                .then(resText => {

                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(emp_promise)

        Promise.all(promises).then(values => {
            console.log(values)
        })
    }
}

export const fetchDbBegin = () => ({
    type: FETCH_DB_BEGIN
});

export const fetchDbSuccess = (data) => ({
    type: FETCH_DB_SUCCESS,
    payload: { data }
});

export const fetchDbFailure = (err) => ({
    type: FETCH_DB_FAILURE,
    payload: { err }
});

Я выполняю рефакторинг компонента класса React для использования Redux. Изначально все вызовы API были внутри componentDidMount, и это было настолько грязно.

Я использую redux-thunk, чтобы убрать это из компонента класса.

fetchDatabase в моемdatabaseAction.js делает все, что componentDidMount делал в компоненте класса.

Обычно, если бы это был один вызов API, я бы просто отправил fetchDbSuccess, поскольку вызов API был выполнен успешно. Однако, используя Promise.All, который принимает три асинхронных вызова API, я не уверен, должен ли я

  1. создать отдельное действие для каждого вызова API (fetchProfileSuccess, fetchReleaseSuccess и fetchUserSuccess) и отправьте каждый из них в конце каждого Обещания (место, где я ввел //Use Dispatch Here? в коде.

ИЛИ

Просто отправьте один fetchDbSuccess, когда Promise.all будет разрешен.

Если я решу сделать 2, я должен обновить все три states в моем редукторе?

Спасибо

1 Ответ

2 голосов
/ 11 октября 2019

Отправлять и обновлять состояние следует только в том случае, если у вас есть код, который заботится об указанных обновлениях состояния. Например, если вы просто хотите показать один счетчик, тогда уберите счетчик, когда он будет полностью завершен, вашему пользователю не обязательно заботиться о каждой атомарной операции, поэтому вам не нужно, чтобы она отображалась в состоянии. Если у вас есть пользовательский интерфейс, который отображает каждый из них, то вы захотите эти дополнительные рассылки.

Кстати, ваши Обещания выглядят немного слишком сложными. Если вы решите, что вам не нужны эти дополнительные изменения состояния, вы можете упростить это до следующего:

export const FETCH_DB_BEGIN = 'FETCH_DB_BEGIN'
export const FETCH_DB_SUCCESS = 'FETCH_DB_SUCCESS'
export const FETCH_DB_FAILURE = 'FETCH_DB_FAILURE'

export const fetchDatabase = () => {
    return dispatch => {
        dispatch(fetchDbBegin());

        const urls = [
            'http://localhost:5000/profiles',
            'http://localhost:5000/releases',
            'http://localhost:5000/users'
        ];

        const options = {
            headers: header,
            method: 'get',
            mode: 'cors',
            body: null,
        }

        const fetchJson = url => fetch(url, options).then(res => res.json());

        Promise.all(urls.map(fetchJson))
            .then(([profile, release, employee]) => {
                dispatch(fetchDbSuccess({ profile, release, employee }));
            })
            .catch(err => {
                dispatch(fetchDbFailure(err));
            });
    }
}

export const fetchDbBegin = () => ({
    type: FETCH_DB_BEGIN
});

export const fetchDbSuccess = (data) => ({
    type: FETCH_DB_SUCCESS,
    payload: { data }
});

export const fetchDbFailure = (err) => ({
    type: FETCH_DB_FAILURE,
    payload: { err }
});
...