如何在反应中使用redux取消以前的axios
Posted
技术标签:
【中文标题】如何在反应中使用redux取消以前的axios【英文标题】:how to cancel previous axios with redux in react 【发布时间】:2018-08-20 09:24:54 【问题描述】:我的操作文件中有以下操作。
import axios from 'axios';
import $ from 'jquery';
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
export const FETCH_WORKERJOBS = 'fetch_workerjobs';
export function fetchWorkerJobs(page, size, where, sort)
const request = axios.get(`/api/user/report/comms/matrix/upload/format/json?quiet=1&page=`+page+`&size=`+size+`&where=`+JSON.stringify(where)+`&sort=`+sort,cancelToken: source.token);
return
type: FETCH_WORKERJOBS,
payload: request
;
export const FETCH_WORKERJOBS_COUNT = 'fetch_workerjobs_count';
export function fetchWorkerJobsCount(where)
const request = axios.get(`/api/user/report/comms/matrix/upload/count/format/json?quiet=1&where=`+JSON.stringify(where), cancelToken: source.token);
return
type: FETCH_WORKERJOBS_COUNT,
payload: request
;
当我将函数导入我的组件时,如何访问cancel
令牌以取消
import _ from 'lodash';
import React, Component from 'react';
import connect from 'react-redux';
import fetchWorkerJobs, fetchWorkerJobsCount from '../../actions';
import Link from 'react-router-dom';
import bindActionCreators from 'redux';
import Button, ButtonToolbar, Modal from 'react-bootstrap';
import FontAwesome from 'react-fontawesome';
import
BootstrapTable,
TableHeaderColumn,
InsertModalHeader,
InsertModalFooter
from 'react-bootstrap-table';
import 'react-bootstrap-table/dist/react-bootstrap-table-all.min.css';
import $ from 'jquery';
const jobType =
class WorkerJobs extends Component
constructor(props)
super(props);
this.workerJobs = [];
this.state =
data: [],
show: false,
showError: false,
errorMsg: '',
errorTitle: '',
record: ,
showEdit: false,
confirm:
body: '',
show: false,
id: ''
,
totalDataSize: 0,
currentPage: 1
;
this.where = ;
this.sort = 'worker_job_id desc';
this.meta = title: 'Report - Worker Jobs', description: 'List of jobs processed' ;
this.error = show: false,msg:'';
this.passMetaBack = this.passMetaBack.bind(this);
this.options =
defaultSortName: 'worker_job_id', // default sort column name
defaultSortOrder: 'desc', // default sort order
page: 1,
paginationShowsTotal: true,
sizePerPage: 10,
sizePerPageList: [10,25,50],
onPageChange: this.onPageChange.bind(this),
onSizePerPageList: this.onSizePerPageList.bind(this),
onFilterChange: this.onFilterChange.bind(this),
onSortChange: this.onSortChange.bind(this)
;
this.fetchWorkerJobs = this.fetchWorkerJobs.bind(this);
this.runOnce = false;
onPageChange(page, sizePerPage)
const currentIndex = (page - 1) * sizePerPage;
this.options.page = page;
console.log(this.props);
this.props.fetchWorkerJobsCount.cancel(); //not working
this.props.fetchWorkerJobs.cancel(); //not working
console.log(this.props);
this.fetchWorkerJobs(page, sizePerPage, this.where, this.sort);
onSizePerPageList(sizePerPage)
const currentIndex = (this.state.currentPage - 1) * sizePerPage;
this.options.sizePerPage = sizePerPage;
this.fetchWorkerJobs(this.options.page, sizePerPage, this.where, this.sort);
onFilterChange(filterObj)
let where = ;
for (const key in filterObj)
where[key] = filterObj[key].value;
this.where = where;
this.fetchWorkerJobs(this.options.page,this.options.sizePerPage,this.where, this.sort);
onSortChange(sortName, sortOrder)
this.sort = sortName + " " + sortOrder;
this.fetchWorkerJobs(this.options.page,this.options.sizePerPage,this.where, this.sort);
fetchWorkerJobs(page, size, where, sort)
let self = this;
this.props.fetchWorkerJobsCount(where).then(function(response)
let data = response.payload.data;
if(data.header.error)
//@todo show error on input form
//self.handleShowError(data.header.message);
else
return data.body.recordset.record;
)
.then((count)=>
this.props.fetchWorkerJobs(page, size, where, sort).then(function(response)
let data = response.payload.data;
if(data.header.error)
//@todo show error on input form
//self.handleShowError(data.header.message);
else
self.options.page = page;
self.options.sizePerPage = size;
self.workerJobs = data.body.recordset.record;
self.setState(
data : data.body.recordset.record,
totalDataSize : count
);
);
);
moveElement()
//store a this ref, and
var _this = this;
//wait for a paint to do scrolly stuff
window.requestAnimationFrame(function()
if($(".react-bs-table-tool-bar").length > 0)
if($(".react-bs-table-tool-bar .react-bs-table-sizePerPage-dropdown").length <= 0)
$(".react-bs-table-sizePerPage-dropdown").prependTo(".react-bs-table-tool-bar");
);
renderTable(services)
return (
<BootstrapTable
keyField="worker_job_id"
data=services
remote
//multiColumnSearch
fetchInfo= dataTotalSize: this.state.totalDataSize
options=this.options
pagination
striped
hover
//insertRow
//search
tableHeaderClass="table-vf thead"
exportCSV
tableContainerClass="report_workerjobs"
>
<TableHeaderColumn dataField="worker_job_id" dataSort=true width=`60px`>
#
</TableHeaderColumn>
<TableHeaderColumn dataField="job" filter= type: 'SelectFilter', options: jobType >Job</TableHeaderColumn>
<TableHeaderColumn dataField="filename">Filename</TableHeaderColumn>
<TableHeaderColumn
dataField="flag"
filter= type: 'TextFilter', defaultValue: 'C'
width=`60px`
>
Flag
</TableHeaderColumn>
<TableHeaderColumn dataField="total_time_taken" width=`125px`>Total Time Taken</TableHeaderColumn>
<TableHeaderColumn dataField="output" width=`100px`>Analysis</TableHeaderColumn>
<TableHeaderColumn dataField="ts_created">Created</TableHeaderColumn>
<TableHeaderColumn dataField="ts_updated">Finished</TableHeaderColumn>
<TableHeaderColumn dataField="comms_matrix_id" width=`60px`>#CM</TableHeaderColumn>
<TableHeaderColumn dataField="visible_lines" width=`100px`>Visible Lines</TableHeaderColumn>
<TableHeaderColumn
dataField="security_flows"
width=`100px`
thStyle=
whiteSpace: 'pre-wrap',
whiteSpace: '-moz-pre-wrap',
whiteSpace: '-pre-wrap',
whiteSpace: '-o-pre-wrap',
wordWrap: 'break-word'
>
Security Flows
</TableHeaderColumn>
</BootstrapTable>
);
render()
if(!this.runOnce && this.props.isReady)
this.runOnce = true;
this.fetchWorkerJobs(this.options.page, this.options.sizePerPage, this.where, this.sort);
let table = <div>Loading...<i className="fa fa-spinner fa-spin"></i></div>;
if ( Object.keys(this.props.reportsWorkerJobs).length > 0)
table = this.renderTable(this.state.data);
this.moveElement();
return (
<div className="container-fluid">
<div className="row-fluid top-buffer">table</div>
</div>
);
function mapStateToProps(state)
return
reportsWorkerJobs: state.reportsWorkerJobs,
reportsWorkerJobsCount: state.reportsWorkerJobsCount
;
function mapDispatchToProps(dispatch)
return bindActionCreators(
fetchWorkerJobs, fetchWorkerJobsCount ,
dispatch
);
export default connect(mapStateToProps, mapDispatchToProps)(WorkerJobs);
我想取消以前的分页请求等。我需要取消
this.props.fetchWorkerJobsCount.cancel(); //not working
this.props.fetchWorkerJobs.cancel(); //not working
我尝试从动作文件中导出变量并导入到组件中,但不起作用
actions.js
export const FETCH_WORKERJOBS_COUNT_CANCEL = wjc_cancel;
组件
...
import fetchWorkerJobs, fetchWorkerJobsCount, FETCH_WORKERJOBS_COUNT_CANCEL, FETCH_WORKERJOBS_CANCEL from '../../actions';
...
onPageChange(page, sizePerPage)
const currentIndex = (page - 1) * sizePerPage;
this.options.page = page;
FETCH_WORKERJOBS_COUNT_CANCEL();
FETCH_WORKERJOBS_CANCEL();
this.fetchWorkerJobs(page, sizePerPage, this.where, this.sort);
我得到的错误是Uncaught TypeError: (0 , _actions.FETCH_WORKERJOBS_COUNT_CANCEL) is not a function
更新
我试图将它作为变量传递给操作函数,但一些请求似乎通过了。我正在做的是非常快地按下分页上的下一个按钮。大多数会被取消,但有些不会。
export function fetchWorkerJobs(page, size, where, sort, cancelled)
if(cancelled)
wj_cancel();
const request = axios.get(`/api/user/report/comms/matrix/upload/format/json?quiet=1&page=`+page+`&size=`+size+`&where=`+JSON.stringify(where)+`&sort=`+sort,
cancelToken: new CancelToken(function executor(c)
// An executor function receives a cancel function as a parameter
wj_cancel = c;
)
);
return
type: FETCH_WORKERJOBS,
payload: request
;
【问题讨论】:
【参考方案1】:您需要访问source
变量才能取消它。
或者,您可以在创建新请求时取消先前的请求(这似乎是您的用例)。
类似于以下内容(使用执行器函数语法:https://github.com/axios/axios#cancellation,因此您会为每个请求获得一个新令牌)
import axios from 'axios';
import $ from 'jquery';
var CancelToken = axios.CancelToken;
let wj_cancel, wjc_cancel;
export const FETCH_WORKERJOBS = 'fetch_workerjobs';
export function fetchWorkerJobs(page, size, where, sort)
wj_cancel && wj_cancel();
const request = axios.get(`/api/user/report/comms/matrix/upload/format/json?quiet=1&page=` + page + `&size=` + size + `&where=` + JSON.stringify(where) + `&sort=` + sort,
cancelToken: new CancelToken(function executor(c)
// An executor function receives a cancel function as a parameter
wj_cancel = c;
);
return
type: FETCH_WORKERJOBS,
payload: request
;
export const FETCH_WORKERJOBS_COUNT = 'fetch_workerjobs_count';
export function fetchWorkerJobsCount(where)
wjc_cancel && wjc_cancel();
const request = axios.get(`/api/user/report/comms/matrix/upload/count/format/json?quiet=1&where=` + JSON.stringify(where),
cancelToken: new CancelToken(function executor(c)
// An executor function receives a cancel function as a parameter
wjc_cancel = c;
);
return
type: FETCH_WORKERJOBS_COUNT,
payload: request
;
【讨论】:
我如何从我的组件访问let wj_cancel, wjc_cancel;
@shorif2000 这个想法是fetchWorkerJobsCount
和fetchWorkerJobs
在您尝试进行新的提取时会自行调用它。
哦...这在任何地方都没有写得很清楚。让我感到困惑。
@shorif2000 或者,您可以导出这两个变量并将它们导入以在您的组件中使用。
export const FETCH_WORKERJOBS_COUNT_CANCEL = wjc_cancel;
导出另一个变量,其初始值为wjc_cancel
,即undefined
。您需要直接导出wjc_cancel
。 export wj_cancel;
【参考方案2】:
下面是可以使用的代码:
// get info in component
useEffect(() =>
const cancelToken = customAxios.CancelToken.source();
dispatch(fetchStream(match.params.id, cancelToken.token));
return () =>
cancelToken.cancel(`Cancel fetchStream $match.params.id`)
, []);
// where fetchStream in store/actions/streams.js
export const fetchStream = (id, cancelToken) => async dispatch =>
try
const data: stream = await axios.get(`/streams/$id`,
cancelToken
);
dispatch(
type: FETCH_STREAM,
payload: stream
)
catch (e)
console.log("fetchStream get error ", e);
;
【讨论】:
以上是关于如何在反应中使用redux取消以前的axios的主要内容,如果未能解决你的问题,请参考以下文章
在 useEffect 挂钩中使用 axios 取消令牌时如何修复失败的测试