Redux:在成功函数上使用异步中间件与分派操作 [英] Redux: Using async middlewares vs dispatching actions on success functions

查看:18
本文介绍了Redux:在成功函数上使用异步中间件与分派操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 Redux 集成到我的 React 项目中.目前我没有使用任何 Flux 框架.

I am trying to integrate Redux into my React project. Currently I'm not using any Flux framework.

我的应用程序从 API 获取一些数据并以漂亮的方式显示它,如下所示:

My app gets some data from the API and displays it in a pretty way, like so:

componentDidMount() {
  getData();
}

getData() {
  const self = this;

  ajax({
    url: apiUrl,
  })
  .success(function(data) {
    self.setState({
      data: data,
    });
  })
  .error(function() {
    throw new Error('Server response failed.');
  });
}

在阅读 Redux 时,我确定了两种可能的方法来处理将我的成功数据存储在商店中:

In reading about Redux, I've settled on two possible approaches that I could use for handling storing my success data in the store:

  • 使用异步中间件,或
  • 从ajax函数的成功回调中调度动作ADD_DATA

但我不确定哪种方法更好.

But I'm unsure which is the better approach.

在回调中分派动作听起来很容易实现和理解,而异步中间件很难向不习惯使用函数式语言的人解释.

Dispatching action in callback sounds easy to implement and understand, while async middlewares are harder to explain to people who are not used to working with a functional language.

推荐答案

我个人更喜欢使用自定义中间件来实现这一点.它使操作更容易遵循,并且 IMO 的样板文件更少.

I personally prefer using custom middleware to accomplish this. It makes the actions a little easier to follow and has less boilerplate IMO.

我已经设置了我的中间件来查找从匹配某个签名的操作返回的对象.如果找到这个对象模式,它会专门处理它.

I've set up my middleware to look for an object returned from a action that matches a certain signature. If this object schema is found, it handles it specially.

例如,我使用如下所示的操作:

For example, I use an action that looks like this:

export function fetchData() {
  return {
    types: [ FETCH_DATA, FETCH_DATA_SUCCESS, FETCH_DATA_FAILURE ],
    promise: api => api('foo/bar')
  }
}

我的自定义中间件看到该对象有一个 types 数组和一个 promise 函数并专门处理它.这是它的样子:

My custom middleware sees that the object has a types array and a promise function and handles it specially. Here's what it looks like:

import 'whatwg-fetch';

function isRequest({ promise }) {
  return promise && typeof promise === 'function';
}

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  } else {
    const error = new Error(response.statusText || response.status);
    error.response = response.json();
    throw error;
  }
}

function parseJSON(response) {
  return response.json();
}

function makeRequest(urlBase, { promise, types, ...rest }, next) {
  const [ REQUEST, SUCCESS, FAILURE ] = types;

  // Dispatch your request action so UI can showing loading indicator
  next({ ...rest, type: REQUEST });

  const api = (url, params = {}) => {
    // fetch by default doesn't include the same-origin header.  Add this by default.
    params.credentials = 'same-origin';
    params.method = params.method || 'get';
    params.headers = params.headers || {};
    params.headers['Content-Type'] = 'application/json';
    params.headers['Access-Control-Allow-Origin'] = '*';

    return fetch(urlBase + url, params)
      .then(checkStatus)
      .then(parseJSON)
      .then(data => {
        // Dispatch your success action
        next({ ...rest, payload: data, type: SUCCESS });
      })
      .catch(error => {
        // Dispatch your failure action
        next({ ...rest, error, type: FAILURE });
      });
  };

  // Because I'm using promise as a function, I create my own simple wrapper
  // around whatwg-fetch. Note in the action example above, I supply the url
  // and optionally the params and feed them directly into fetch.

  // The other benefit for this approach is that in my action above, I can do 
  // var result = action.promise(api => api('foo/bar'))
  // result.then(() => { /* something happened */ })
  // This allows me to be notified in my action when a result comes back.
  return promise(api);
}

// When setting up my apiMiddleware, I pass a base url for the service I am
// using. Then my actions can just pass the route and I append it to the path
export default function apiMiddleware(urlBase) {
  return function() {
    return next => action => isRequest(action) ? makeRequest(urlBase, action, next) : next(action);
  };
}

我个人喜欢这种方法,因为它集中了很多逻辑,并为您提供了 API 操作结构的标准实施方式.这样做的缺点是,对于那些不熟悉 redux 的人来说,它可能有点神奇.我也使用 thunk 中间件,到目前为止,这两个中间件一起解决了我的所有需求.

I personally like this approach because it centralizes a lot of the logic and gives you a standard enforcement of how api actions are structured. The downside to this is that it could be a little magical to those who aren't familiar with redux. I also use thunk middleware also and both of these together solve all my needs so far.

这篇关于Redux:在成功函数上使用异步中间件与分派操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆