Redux:使用异步中间件与成功功能上的调度动作 [英] Redux: Using async middlewares vs dispatching actions on success functions

查看:115
本文介绍了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天全站免登陆