[译]在 React & Redux 中使用 AJAX 轮询

更新: 查看最新关于使用 redux-saga 进行轮询的文章:notjoshmiller.com/ajax-pollin…javascript

正如生活不老是给予你所需之物,你所用的 API 也不老是支持流式事件。所以,当你须要把一些有时序依赖的状态从服务端同步到客户端时,一个经常使用的 “曲线救国” 方法就是使用 AJAX 进行接口轮询。咱们大部分人都知道使用 setInterval 并非处理轮询的 “最佳人选”,不过它的堂兄 setTimeout 配合 递归解法 却能够大展身手。前端

React & Redux 为咱们提供了响应式的数据流,咱们如何才能使普通的轮询方法与其和谐共处?RxJS 以及其余 Observable 类库是处理轮询的不错选择,不过除非你的项目已经集成了 Observable 类库,不然仅为解决轮询而引入相关类库显得并不值当。当前经过结合 React 组件的生命周期方法和 Redux 的 Action 就已经足够处理 AJAX 轮询,下面来看看如何得解?java

首先经过 Redux 的 Reducer 来讲明当前 State:react

const initialState = {  
    data: {},
    isFetching: false
};

export function data (state = initialState, action) {  
    switch (action.type) {
    case DATA_FETCH_BEGIN: {
        return { ...state, isFetching: true };
    }
    case DATA_FETCH_SUCCESS: {
        return { isFetching: false, data: { ...state.data, action.payload }};
    }
    case DATA_FETCH_ERROR: {
        return { ...state, isFetching: false };
    }
    default:
        return state;
}
复制代码

我不会在这里去讲解如何处理 Redux 中的异步 Action 建立函数,想更好地了解这方面知识请参考 Redux 文档中的异步示例。 如今只需假设咱们已有相关的 Redux 中间件来处理本文提到的各类 Action 。我会使用与 real-world example(译注:原文连接的仓库已不存在,能够参考 Redux 文档中同名例子)中类似形式的 Action 建立函数。jquery

对应上方的数据模型,咱们的 Action 建立函数可能为:android

export function dataFetch() {  
  return {
    [CALL_API]: {
      types: [DATA_FETCH_BEGIN, DATA_FETCH_SUCCESS, DATA_FETCH_ERROR],
      endpoint: 'api/data/'
    }
  };
}
复制代码

回到最初的问题,让咱们想一想你会如何实现 API 接口的轮询。你会把轮询的定时器设置在 Reducer 中?仍是 Action 建立函数里?或许是中间件里?若是把定时器放到 Smart 组件(译注:参看 Smart and Dumb Components - Medium)中怎么样呢?我会选择在组件中设置定时器,不只是由于组件须要控制自身的数据依赖,并且咱们能够经过组件的生命周期方法控制这些定时器,看看如何作到?ios

import React from 'react';  
import {connect} from 'react-redux';  
import {bindActionCreators} from 'redux';  
import * as DataActions from 'actions/DataActions';

// 组件须要哪些 Redux 全局状态做为 props 传入?
function mapStateToProps(state) {  
    return {
        data: state.data.data,
        isFetching: state.data.isFetching
    };
}

// 组件须要哪些 Action 建立函数做为 props 传入?
function mapDispatchToProps(dispatch) {  
    return {
        dataActions: bindActionCreators(DataActions, dispatch)
    };
}

@connect(mapStateToProps, mapDispatchToProps)
export default class AppContainer {  
    componentWillReceiveProps(nextProps) {
        if (this.props.data !== nextProps.data) {

            clearTimeout(this.timeout);

            // 你能够在这里处理获取到的数据

            if (!nextProps.isFetching) {
                this.startPoll();
            }
        }

    }

    componentWillMount() {
        this.props.dataActions.dataFetch();
    }

    componentWillUnmount() {
        clearTimeout(this.timeout);
    }

    startPoll() {
        this.timeout = setTimeout(() => this.props.dataActions.dataFetch(), 15000);
    }
}
复制代码

好了,大功告成。由于上面的组件须要一些额外数据进行渲染,因此它会在挂载的时候尝试获取这些数据。 当 dataFetch 发送了一个新 Action 后,咱们的 Reducer 会返回新的状态, 进而触发组件的 componentWillReceiveProps 方法。在这个生命周期方法内会首先清除全部进行中的定时器,若当前没有进行数据请求则随即启动一个新定时器。git

诚然还有不少方法能够处理这里的接口轮询问题,而且若是有任何长轮询方法可用时,此处的轮询方法便相形见绌。不过我仍是但愿这篇文章能够帮助阐明结合 React 生命周期方法和 Redux 数据流的处 “事” 之道。github


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏ajax

相关文章
相关标签/搜索