如何使用Fetch保证HTTP请求的成功

时间:2017-01-10 09:11:29

标签: http redux fetch redux-thunk

我正在尝试了解处理fetch HTTP请求的正确方法,并确保收到请求的数据。

我的观点是我的请求可能出现问题,所需的数据对我的应用程序至关重要。在那种情况下,处理它的更合适的方法是什么?只需创建一个新请求?

我如何将解决方案与reduxredux-thunk

结合起来

由于

1 个答案:

答案 0 :(得分:1)

编写使用fetch执行HTTP请求的Redux Thunk Action Creator指南

<强>序言

此示例使用isomorphic-fetch,它是一个基于promise的库,用于发出HTTP请求。但是,您可以使用不同的基于承诺的请求库(例如Axios)运行此示例,它仍然可以使用。如果您不想使用其中一个库,可以将自己的HTTP请求包装在一个承诺中。

Quick Redux Thunk示例

首先,这是一个从redux-thunk docs借来的自包含示例

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

// set up store with redux thunk
const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

// thunk action creator
function makeASandwichWithSecretSauce(forPerson) {
  return function (dispatch) {
    return fetchSecretSauce().then(
      sauce => dispatch(makeASandwich(forPerson, sauce)),
      error => dispatch(apologize('The Sandwich Shop', forPerson, error))
    );
  };
}

// we can now dispatch the result of our thunk action creator like any other action
store.dispatch(makeASandwichWithSecretSauce('bob))

使用Redux操作表示HTTP请求的有状态

来自Redux文档:

  

当您调用异步API时,有两个关键时刻   时间:你开始通话的那一刻,以及你收到的那一刻   答案(或超时)。我们首先需要定义动作及其动作   与对异步调用相关联的创建者   任何给定主题id的外部资源。

承诺有三种可能的状态代表API请求:

  • 待定(请求)
  • 完成(请求成功)
  • 拒绝(请求失败 - 或超时)

代表请求承诺状态的核心动作创建者

好的,我们可以编写核心动作创建者来表示给定主题ID的请求的有状态。

const fetchPending = (topicId) => {
  return { type: 'FETCH_PENDING', topicId }
}

const fetchFulfilled = (topicId, response) => { 
  return { type: 'FETCH_FULFILLED', topicId, response }
}

const fetchRejected = (topicId, err) => {
  return { type: 'FETCH_REJECTED', topicId, err }
}

请注意,您的Reducer应该适当地处理这些操作。

单个抓取操作创建者的逻辑

Fetch是一个基于承诺的请求库。所以axios.get方法向给定的url发出请求并返回一个将在成功时解析的promise,否则这个promise将被拒绝

import fetch from 'isomorphic-fetch'

const makeAPromiseAndHandleResponse = (topicId, url, dispatch) => {
    return fetch(url)
             .then(response => {
               dispatch(fetchFulfilled(topicId, response))
             })
             .catch(err => {
               dispatch(fetchRejected(topicId, err))
             }) 
}

如果我们的HTTP请求成功,我们的承诺将得到解决,并且.then中的代码将被执行。这将根据我们的请求(我们的主题数据)为我们的给定主题id调度FETCH_FULFILLED操作

如果HTTP请求不成功,我们将在.catch中执行代码并调度FETCH_REJECTED操作,该操作将包含主题ID和请求期间发生的错误。

我们将请求错误处理逻辑放在这里。这可能涉及调度一个或多个可能重新尝试HTTP请求或将另一个请求发送到备用URL的其他操作。

由于这是一个异步过程,我们可以使用thunk动作创建器,它将使用Redux-thunk中间件来允许我们在将来发送额外的异步动作。

Thunk Action创建者如何运作?

我们的thunk action creator能够在将来的某个日期发送多个动作。

它将调度的一组操作为我们的Reducer提供有关HTTP请求状态的信息。

Thunk这个词与延迟评估同义。

这个单一的thunk动作创建者是一个动作创建者,它将由我们的redux thunk中间件处理,因为它适合与thunk动作创建者相关联的签名,即它返回一个函数。

编写我们的thunk action creator

export const fetchSomeStuff = (url) => {
    return dispatch => {
        fetchData().then(
            response => dispatch(setOurData(response.data)),
            error => dispatch(apologise(error))
        );
    };
}

我们的thunk action creator返回一个函数。这个函数可以返回它想要的任何正常函数,所以如果我们想要,我们可以设置它来返回一个promise。

export const fetchSomeStuff = (url) => {
    return dispatch => {
        return fetchData().then(
            response => dispatch(setOurData(response.data)),
            error => dispatch(apologise(error))
        );
    };
}

上面的fetchSomeStuff函数是一个thunk动作创建器,它从isomorphic-fetch调用fetch。因此,此动作创建者返回一个承诺。

因为当我们调用fetchSomeStuff(我们的thunk action creator)时,我们将在thunk action creator返回的函数内返回此函数,我们将返回一个promise。这非常有用,特别是对于我们可能想要检查在我们调用thunk动作创建者之后的某个时间点调度某些操作的测试。

我们的thunk action creator返回我们在fetchSomeStuff thunk动作创建器中返回的函数。

这是Redux thunk里面的代码:

if (typeof action === 'function') {
  return action(dispatch, getState);
}

所以如果我们打电话

fetchSomeStuff('www.example.com')

我们返回了一个函数

但是如果我们发送fetchSomeStuff

store.dispatch(fetchAllItems('www.example.com'))

我们退回了一个承诺。

这两行代码之间的区别在于,当我们调度我们的thunk动作创建器而不是简单地调用它时,它会通过中间件链。 Redux thunk知道如何处理函数并会调用它们。

基本上这就是当配置了redux-thunk中间件并且我们调用store.dispatch

时会发生什么

我们有被派遣的thunk

function thunkActionCreator(){
   return function middlewareInjectsStoreMethods({dispatch, getstate}){  
   }
}

当我们派遣此动作创作者

return action(dispatch, getState, extraArgument);

我们之前在redux thunk中看到过的代码将被执行

if (typeof action === 'function') {
  return action(dispatch, getState)
}

我们返回在thunk action creator中调用嵌套函数的结果

function thunkActionCreator(){
   return function middlewareInjectsStoreMethods({dispatch, getstate}){
   }
}

if (typeof action === 'function') {
    return action(dispatch, getState)
}

action代表我们的thunk动作创建者,而内部调用action意味着我们返回名为middlewareInjectsStoreMethods的嵌套函数 而呼叫

 return action(dispatch, getState) 

返回我们的嵌套函数(middlewareInjectsStoreMethods)并给出商店的dispatch和getState方法。

在心理上,我们可以将redux-thunk视为这样做

if (typeof thunkActionCreator  === 'function') {
     return function middlewareInjectsStoreMethods({dispatch,  getstate}){}
}

所以现在我们可以看到为什么我们必须在redux thunk动作创建器中返回一个函数。 我们的行动创建者需要访问以便在将来发布进一步的行动。通过返回一个函数,我们可以在以后调用它,并且STILL可以访问调度。这种优雅的做事方式是我成为Redux粉丝的部分原因。