Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React redux api每x秒轮询一次_Reactjs_Redux_Polling - Fatal编程技术网

Reactjs React redux api每x秒轮询一次

Reactjs React redux api每x秒轮询一次,reactjs,redux,polling,Reactjs,Redux,Polling,我已经做到了,但我追求的是一种更“最佳实践方式” 它使用api显示每x秒更新一次的随机笑话。有更好的方法吗 最终,我想添加停止、启动、重置功能,并觉得这种方式可能不是最好的 我可以使用任何中间件吗 重演行动 // action types import axios from 'axios'; export const FETCH_JOKE = 'FETCH_JOKE'; export const FETCH_JOKE_SUCCESS = 'FETCH_JOKE_SUCCESS'; export

我已经做到了,但我追求的是一种更“最佳实践方式”

它使用api显示每x秒更新一次的随机笑话。有更好的方法吗

最终,我想添加停止、启动、重置功能,并觉得这种方式可能不是最好的

我可以使用任何中间件吗

重演行动

// action types
import axios from 'axios';
export const FETCH_JOKE = 'FETCH_JOKE';
export const FETCH_JOKE_SUCCESS = 'FETCH_JOKE_SUCCESS';
export const FETCH_JOKE_FAILURE = 'FETCH_JOKE_FAILURE';


function fetchJoke() {
  return {
    type: FETCH_JOKE
  };
}

function fetchJokeSuccess(data) {
  return {
    type: FETCH_JOKE_SUCCESS,
    data
  };
}

function fetchJokeFail(error) {
  return {
    type: FETCH_JOKE_FAILURE,
    error
  };
}

export function fetchJokeCall(){
  return function(dispatch){
    dispatch(fetchJoke());
    return axios.get('https://icanhazdadjoke.com', { headers: { 'Accept': 'application/json' }})
    .then(function(result){
      dispatch(fetchJokeSuccess(result.data))
    })
    .catch(error => dispatch(fetchJokeFail(error)));
  }
}
Redux减速器

import {combineReducers} from 'redux';
import {FETCH_JOKE, FETCH_JOKE_SUCCESS, FETCH_JOKE_FAILURE} from '../actions';

const defaultStateList = {
  isFetching: false,
  items:[],
  error:{}
};

const joke = (state = defaultStateList, action) => {
  switch (action.type){
  case FETCH_JOKE:
    return {...state, isFetching:true};
  case FETCH_JOKE_SUCCESS:
    return {...state, isFetching:false, items:action.data};
  case FETCH_JOKE_FAILURE:
    return {...state, isFetching:false, error:action.data};
  default:
    return state;
  }
};

const rootReducer = combineReducers({
  joke
});

export default rootReducer;
笑话成分

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { fetchJokeCall } from '../actions';


class Joke extends Component {
  componentDidMount() {
    this.timer = setInterval(()=>  this.props.fetchJokeCall(), 1000);
  }
  componentWillUnmount() {
    clearInterval(this.timer)
    this.timer = null;
  }
  render() {
    return (
      <div>
        {this.props.joke.joke}
      </div>
    );
  }
}

Joke.propTypes = {
  fetchJokeCall: PropTypes.func,
  joke: PropTypes.array.isRequired
};

function mapStateToProps(state) {
  return {
    joke: state.joke.items,
    isfetching: state.joke.isFetching
  };
}

export default connect(mapStateToProps, { fetchJokeCall })(Joke);
import React,{Component}来自'React';
从'react redux'导入{connect};
从“道具类型”导入道具类型;
从“../actions”导入{fetchJokeCall};
类扩展组件{
componentDidMount(){
this.timer=setInterval(()=>this.props.fetchJokeCall(),1000);
}
组件将卸载(){
clearInterval(这个.timer)
this.timer=null;
}
render(){
返回(
{这个。道具。笑话。笑话}
);
}
}
笑话.propTypes={
fetchJokeCall:PropTypes.func,
笑话:需要PropTypes.array.isRequired
};
函数MapStateTops(状态){
返回{
笑话:state.joke.items,
isfetching:state.joke.isfetching
};
}
导出默认连接(MapStateTops,{fetchJokeCall})(笑话);
很棒,我一直在用redux。它提供了一个很好的api来执行延迟、轮询、限制、竞争条件和任务取消等操作。因此,使用redux传奇,您可以添加一个观察者,该观察者将继续使用池

函数*pollSagaWorker(操作){
while(true){
试一试{
const{data}=yield调用(()=>axios({url:ENDPOINT}));
收益率卖出(GetDataSuccesAction(data));
收益呼叫(延迟,4000);
}捕捉(错误){
产量投入(getDataFailureAction(err));
}
}

}
Redux Sagas更好,我们也在应用程序中使用它,这就是使用Redux Sagas进行投票的方式

为了让您了解这是如何做到的,您还需要了解Redux传奇是如何工作的

行动

export const FETCH_JOKE = 'FETCH_JOKE';
export const FETCH_JOKE_SUCCESS = 'FETCH_JOKE_SUCCESS';
export const FETCH_JOKE_FAILURE = 'FETCH_JOKE_FAILURE';
export const START_POLLING = 'START_POLLING';
export const STOP_POLLING = 'STOP_POLLING';

function startPolling() {
      return {
        type: START_POLLING
      };
    }

function stopPolling() {
      return {
        type: STOP_POLLING
      };
    }

function fetchJoke() {
  return {
    type: FETCH_JOKE
  };
}

function fetchJokeSuccess(data) {
  return {
    type: FETCH_JOKE_SUCCESS,
    data
  };
}

function fetchJokeFail(error) {
  return {
    type: FETCH_JOKE_FAILURE,
    error
  };
}
减速器

import {combineReducers} from 'redux';
import {FETCH_JOKE, FETCH_JOKE_SUCCESS, FETCH_JOKE_FAILURE, START_POLLING, STOP_POLLING } from '../actions';

const defaultStateList = {
  isFetching: false,
  items:[],
  error:{},
  isPolling: false,
};

const joke = (state = defaultStateList, action) => {
  switch (action.type){
  case FETCH_JOKE:
    return {...state, isFetching:true};
  case FETCH_JOKE_SUCCESS:
    return {...state, isFetching:false, items:action.data};
  case FETCH_JOKE_FAILURE:
    return {...state, isFetching:false, error:action.data};
  case START_POLLING:
    return {...state, isPolling: true};
  case STOP_POLLING:
    return {...state, isPolling: false};
  default:
    return state;
  }
};

const rootReducer = combineReducers({
  joke
});

export default rootReducer;
传奇

import { call, put, takeEvery, takeLatest, take, race } from 'redux-saga/effects'

import {FETCH_JOKE, FETCH_JOKE_SUCCESS, FETCH_JOKE_FAILURE, START_POLLING, STOP_POLLING } from '../actions';

import axios from 'axios';



function delay(duration) {
  const promise = new Promise(resolve => {
    setTimeout(() => resolve(true), duration)
  })
  return promise
}

function* fetchJokes(action) {
  while (true) {
    try {
      const { data } = yield call(() => axios({ url: ENDPOINT }))
      yield put({ type: FETCH_JOKE_SUCCESS, data: data })
      yield call(delay, 5000)
    } catch (e) {
      yield put({ type: FETCH_JOKE_FAILURE, message: e.message })
    }
  }
}

function* watchPollJokesSaga() {
  while (true) {
    const data = yield take(START_POLLING)
    yield race([call(fetchJokes, data), take(STOP_POLLING)])
  }
}

export default function* root() {
  yield [watchPollJokesSaga()]
}

你也可以使用Redux Observable,如果你想更深入地了解这一点,请阅读此

我一直在处理几乎相同的问题,只是我不关心开始和停止投票。由于某些原因,while循环一直冻结我的应用程序,所以我放弃了它,而是像这样设置了我的传奇

import { all, takeLatest, call, put } from 'redux-saga/effects';
import axios from 'axios';

import { API_CALL_REQUEST, API_CALL_SUCCESS, API_CALL_FAILURE, API_CALL_FETCHED } from 
'../actions/giphy';

function apiFetch() {
  let randomWord = require('random-words');
  let API_ENDPOINT = `https://api.giphy.com/v1/gifs/search? 
                   api_key=MYKEY&q=${randomWord()}&limit=12`;
  return axios({
    method: "get",
    url: API_ENDPOINT
 });
}

export function* fetchImages() {
  try {
   const res = yield call(apiFetch)
   const images = yield res.data
   yield put({type: API_CALL_SUCCESS, images})

} catch (e) {
  yield put({type: API_CALL_FAILURE, e})
  console.log('Error fetching giphy data')
 }
}

export default function* giphySaga() {
  yield all([
    takeLatest(API_CALL_REQUEST, fetchImages),
 ]);
}    
然后在我的组件中添加了这个

 componentDidMount() {
   this.interval = setInterval(() => {
   this.props.dispatch({type: 'API_CALL_REQUEST'});
   }, 5000);
  }

componentWillUnmount() {
  clearInterval(this.interval)
}

它正在工作,但希望得到一些关于如何改进的反馈。

这是一个穷人的方法。我不认为这是最好的方式,但它不需要任何额外的图书馆

行动

// action types
import axios from 'axios';

export const START_POLLING_JOKE = 'START_POLLING_JOKE';
export const STOP_POLLING_JOKE = 'STOP_POLLING_JOKE';
export const FETCH_JOKE = 'FETCH_JOKE';
export const FETCH_JOKE_SUCCESS = 'FETCH_JOKE_SUCCESS';
export const FETCH_JOKE_FAILURE = 'FETCH_JOKE_FAILURE';

const defaultPollingInterval = 60000

function startPollingJoke(interval = defaultPollingInterval) {
  return function (dispatch) {
    const fetch = () => dispatch(fetchJoke())
    dispatch({
      type: START_POLLING_JOKE,
      interval,
      fetch,
    })
  }
}

function stopPollingJoke() {
  return {
    type: STOP_POLLING_JOKE
  }
}

function fetchJoke() {
  return {
    type: FETCH_JOKE
  };
}

function fetchJokeSuccess(data) {
  return {
    type: FETCH_JOKE_SUCCESS,
    data
  };
}

function fetchJokeFail(error) {
  return {
    type: FETCH_JOKE_FAILURE,
    error
  };
}

export function pollJokeCall(interval = defaultPollingInterval) {
  return function (dispatch) {
    dispatch(fetchJoke())
    dispatch(startPollingJoke(interval))
  }
}

export function fetchJokeCall() {
  return function(dispatch){
    dispatch(fetchJoke());
    return axios.get('https://icanhazdadjoke.com', { headers: { 'Accept': 'application/json' }})
    .then(function(result){
      dispatch(fetchJokeSuccess(result.data))
    })
    .catch(error => dispatch(fetchJokeFail(error)));
  }
}
还原剂

import {combineReducers} from 'redux';
import {
  START_POLLING_JOKE,
  STOP_POLLING_JOKE,
  FETCH_JOKE, 
  FETCH_JOKE_SUCCESS, 
  FETCH_JOKE_FAILURE,
} from '../actions';

const defaultStateList = {
  isFetching: false,
  items:[],
  error:{},
  pollingId: null,
  polling: false,
};

const joke = (state = defaultStateList, action) => {
  switch (action.type){
  case START_POLLING_JOKE: 
    clearInterval(state.pollingId)
    return {
      ...state,
      polling: true,
      pollingId: setInterval(action.fetch, action.interval),
    }
  }
  case STOP_POLLING_JOKE: 
    clearInterval(state.pollingId)
    return {...state, polling: false, pollingId: null}
  case FETCH_JOKE:
    return {...state, isFetching:true};
  case FETCH_JOKE_SUCCESS:
    return {...state, isFetching:false, items:action.data};
  case FETCH_JOKE_FAILURE:
    return {...state, isFetching:false, error:action.data};
  default:
    return state;
  }
};

const rootReducer = combineReducers({
  joke
});

export default rootReducer;
组件(可能有错误,因为我不习惯对组件进行分类)

import React,{Component}来自'React';
从'react redux'导入{connect};
从“道具类型”导入道具类型;
从“../actions”导入{pollJokeCall,stopPollingJoke};
类扩展组件{
componentDidMount(){
this.props.pollJokeCall()
}
组件将卸载(){
这个.props.stoppolling笑话()
}
render(){
返回(
{这个。道具。笑话。笑话}
);
}
}
笑话.propTypes={
pollJokeCall:PropTypes.func,
Stoppolling笑话:PropTypes.func,
笑话:需要PropTypes.array.isRequired,
};
函数MapStateTops(状态){
返回{
笑话:state.joke.items,
isfetching:state.joke.isfetching
};
}
导出默认连接(mapstatetops,{pollJokeCall,stopPollingJoke})(Joke);
我制作了一个小型(5kb Gzip)助手,用于创建基于redux thunk store的轮询。其思想是有一个逻辑来防止两次注册相同的轮询,在迭代之间有回调等等


您可以试用Thunk中间件,使用您的操作将获取结果发送到您的状态。这是一个非常小的库,使用了很多。他已经在使用redux thunk了,看起来像。我建议您查看Nir Kaufmans关于编写自己的中间件的书。所有这些副作用在中间件中都非常重要。这是否需要
while(true)
循环?好像是我想避免的。谢谢。我以我的示例为基础,使用不同的api填充表。对于redux传奇,这会阻止每次刷新整个表吗?另外,如何使用WebSocket?这条路对性能有好处吗?你能给我看一把这把小提琴吗?也许使用random笑话api()更新了answer@Adam你实现了吗?我想这就是答案,因为你想用redux实现投票?谢谢,我今天做了类似的事情。我可以证实你的例子是有效的,这将有助于帮助他人。但现在我觉得WebSocket可能是一个更好更现代的解决方案。想法?是的,你是对的,我也使用过WebSocket,你不需要轮询,因为你可以实现侦听器和回调函数,但我认为使用WebSocket只获取API数据不是我想做的。我会使用WebSocket进行实时聊天或视频通话。
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { pollJokeCall, stopPollingJoke } from '../actions';


class Joke extends Component {
  componentDidMount() {
    this.props.pollJokeCall()
  }
  componentWillUnmount() {
    this.props.stopPollingJoke()
  }
  render() {
    return (
      <div>
        {this.props.joke.joke}
      </div>
    );
  }
}

Joke.propTypes = {
  pollJokeCall: PropTypes.func,
  stopPollingJoke: PropTypes.func,
  joke: PropTypes.array.isRequired,
};

function mapStateToProps(state) {
  return {
    joke: state.joke.items,
    isfetching: state.joke.isFetching
  };
}

export default connect(mapStateToProps, { pollJokeCall, stopPollingJoke })(Joke);