【问题标题】:What is the better/correct way of using Promise.all with React-Redux-Thunk?将 Promise.all 与 React-Redux-Thunk 一起使用的更好/正确方法是什么?
【发布时间】:2020-02-08 11:09:48
【问题描述】:
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。它最初在 componentDidMount 中包含所有 API 调用,而且非常混乱。

我正在使用redux-thunk 将其从类组件中移出。

databaseAction.js 中的 fetchDatabase 完成了 componentDidMount 在类组件中所做的一切。

通常,如果它是单个 API 调用,我会在 API 调用成功完成后直接发送 fetchDbSuccess。但是,使用需要三个异步 API 调用的 Promise.All,我不确定是否应该

  1. 为每个 API 调用(fetchProfileSuccessfetchReleaseSuccessfetchUserSuccess)创建一个单独的操作,并在每个 Promise 的末尾分派每个操作(我在代码中放置 //Use Dispatch Here? 的地方。

  1. Promise.all 得到解决时,只需调度单个fetchDbSuccess

如果我选择执行 2,我是否应该在我的 reducer 中更新所有三个 states

谢谢

【问题讨论】:

  • 您调度的操作数量取决于您期望发生的状态更新。如果您的 UI 不关心所有三个 fetch,那么只有当顶级 fetch 完成时,您才能执行一个成功操作。如果您想为每个人展示特定的内容,您需要执行单独的操作。
  • @Jacob 谢谢。那么这两种方法都正确吗?
  • 是的。顺便说一句,您的示例代码没有正确执行 Promises,因为 new Promise 回调没有调用 resolvereject (并且 new Promise 包装器不是必需的,因为 fetch() 已经返回 Promises)
  • @Jacob 我应该如何修复它们?最初我在类组件中的.then(resText => ... 之后有this.setState,以便在成功完成提取后更新每个数据,并且它似乎符合我的意图。
  • 我将在答案中发布,以便有更多空间。

标签: javascript reactjs redux redux-thunk


【解决方案1】:

只有当你的代码关心所说的状态更新时,你才应该分派和更新状态。例如,如果您只想显示一个微调器,然后在完全完成后让微调器消失,您的用户不一定关心每个原子操作,因此您不需要在状态中反映它。如果您有一个确实显示每个的 UI,那么您会想要那些额外的调度。

顺便说一句,您的 Promise 看起来有点过于复杂。如果您决定不需要这些额外的状态更改,则可以简化为:

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

【讨论】:

  • 谢谢,@Jacob,这很漂亮。我要澄清的一件事是fetchDbSuccessPromise.all 中被调用了多少次?是不是在所有三个fetchJsons 都解决后才调用它一次?
  • 它只被调用一次。 Promise.all 返回一个常规的 Promise。一旦数组中的所有子 Promise 都成功,它会通过每个结果的数组解析为成功。如果任何子 promise 失败,它会以第一个错误拒绝。
猜你喜欢
  • 2017-07-29
  • 2018-09-18
  • 2019-05-20
  • 1970-01-01
  • 2018-07-08
  • 2021-03-29
  • 2018-06-30
  • 2011-12-16
  • 2018-04-10
相关资源
最近更新 更多