使用 axios 的 redux-thunk 的通用数据加载器
Generic dataloader for redux-thunk using axios
我正在开发一个有很多异步操作的应用程序。我想使用 redux-saga,但大多数人坚持继续使用 redux-thunk。在 redux-thunk 中,在每个 action 中,我们必须使用 then、dispatch、catch 等进行异步操作。这使得看起来 action 如此混乱并且将重复大量代码。我想创建一个通用的 dataLoader 来使用 redux-thunk 和 axios,但无法同时考虑 post(可能是 token 或不是)和 get 选项。
这是我的尝试:
export class Company {
/**
* Generic api data loader
*/
static dataLoader(apiUri, onSuccess, onError, data, ...actionArguments) {
const requestURL = `${API_BASE}${apiuri}`;
try {
let options;
if (data !== undefined) {
// if we have data to post
options = {
method: 'POST',
url: requestURL,
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
};
}
}
return function(dispatch) {
axios(options)
.then(response => {
dispatch({
type: onSucess,
payload: response.data
});
})
.catch(error => {
dispatch({ type: onError, payload: err});
});
}
}
static get(apiUri, onSuccess, onError, ...actionArguments) {
return this.dataLoader(apiUri, onSuccess, onError, undefined, ...actionArguments);
}
/*
* Shorthand POST function
*/
static post(apiUri, onSuccess, onError, data, ...actionArguments) {
return this.dataLoader(apiUri, onSuccess, onError, data, ...actionArguments);
}
}
我想将以下代码转换为进一步的代码:
export function showResultofApartment() {
return (dispatch) => {
dispatch({ type: 'APARTMENT_FETCH_START' });
const token = localStorage.getItem('token');
return axios.get(`${API_URL}/newoffers/apartment/`)
.then((response) => {
console.log('response apart', response.data);
dispatch({ type: 'APARTMENT_FETCH_SUCCESS', payload: response.data });
})
.catch((err) => {
dispatch({ type: 'APARTMENT_FETCH_FAILURE', payload: err });
});
};
}
如此或比这更有效:
export function showResultofApartment() {
return(dispatch) => {
dispatch({ type: APARTMENT_FETCH_START });
const token = localStorage.getItem('token');
return Company.get('/apartments', APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR);
// if post then Company.post('/apartment', APARTMENT_POST_SUCCESS, APARTMENT_POST_ERROR, data)
}
}
这样它只考虑 post 请求(如果数据 !== 未定义)。我应该如何有效地处理 get 和 post ?
好吧,你为什么不这样处理:
Company.js
import { merge } from 'lodash';
import axios from 'axios';
function getHeaders() {
return {
'Content-Type': 'application/json'
};
}
export class Company {
static callAPI(endpoint, extendedOptions, onSuccess, onError) {
const initalHttpData = {
method: 'GET', // By default it's GET in case you didnt specify anything
headers: getHeaders(),
url: `${API_BASE}${endpoint}`
};
// merge takes care of replacing or adding the specific key's provided via the extendedOptions
const options = merge(initalHttpData, extendedOptions);
// Fire the request for the prepared options.
let request = axios(options);
// The request once fired, needs it's success handler and error handler.
return function(dispatch) {
request
.then(response => {
dispatch({
type: onSucess,
payload: response.data
});
})
.catch(error => {
dispatch({ type: onError, payload: err});
});
}
};
}
然后我们可以使用动作专门将东西传递给这个api util:
GET API 调用:
// GET Action
export function showResultofApartment() {
return (dispatch) => {
dispatch({ type: APARTMENT_FETCH_START });
const token = localStorage.getItem('token');
// FOR GET API
return Company.callApi('/apartments', {}, APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR);
}
}
POST API 来电:
// POST Action
export function showResultOfAppartmentPost() {
return (dispatch) => {
dispatch({ type: APARTMENT_FETCH_START });
const token = localStorage.getItem('token');
// This will merge, essentially replace the method=GET once it gets called.
const extendedOptions = {
method: 'POST',
body: JSON.stringify(data),
headers: {
'X-Requested-With': 'XMLHttpRequest',
}
}
// FOR GET API
return Company.callApi('/apartments', extendedOptions, APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR);
}
因此,给出动作,定义它自己的一组 API 正文或请求。
我正在开发一个有很多异步操作的应用程序。我想使用 redux-saga,但大多数人坚持继续使用 redux-thunk。在 redux-thunk 中,在每个 action 中,我们必须使用 then、dispatch、catch 等进行异步操作。这使得看起来 action 如此混乱并且将重复大量代码。我想创建一个通用的 dataLoader 来使用 redux-thunk 和 axios,但无法同时考虑 post(可能是 token 或不是)和 get 选项。
这是我的尝试:
export class Company {
/**
* Generic api data loader
*/
static dataLoader(apiUri, onSuccess, onError, data, ...actionArguments) {
const requestURL = `${API_BASE}${apiuri}`;
try {
let options;
if (data !== undefined) {
// if we have data to post
options = {
method: 'POST',
url: requestURL,
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
};
}
}
return function(dispatch) {
axios(options)
.then(response => {
dispatch({
type: onSucess,
payload: response.data
});
})
.catch(error => {
dispatch({ type: onError, payload: err});
});
}
}
static get(apiUri, onSuccess, onError, ...actionArguments) {
return this.dataLoader(apiUri, onSuccess, onError, undefined, ...actionArguments);
}
/*
* Shorthand POST function
*/
static post(apiUri, onSuccess, onError, data, ...actionArguments) {
return this.dataLoader(apiUri, onSuccess, onError, data, ...actionArguments);
}
}
我想将以下代码转换为进一步的代码:
export function showResultofApartment() {
return (dispatch) => {
dispatch({ type: 'APARTMENT_FETCH_START' });
const token = localStorage.getItem('token');
return axios.get(`${API_URL}/newoffers/apartment/`)
.then((response) => {
console.log('response apart', response.data);
dispatch({ type: 'APARTMENT_FETCH_SUCCESS', payload: response.data });
})
.catch((err) => {
dispatch({ type: 'APARTMENT_FETCH_FAILURE', payload: err });
});
};
}
如此或比这更有效:
export function showResultofApartment() {
return(dispatch) => {
dispatch({ type: APARTMENT_FETCH_START });
const token = localStorage.getItem('token');
return Company.get('/apartments', APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR);
// if post then Company.post('/apartment', APARTMENT_POST_SUCCESS, APARTMENT_POST_ERROR, data)
}
}
这样它只考虑 post 请求(如果数据 !== 未定义)。我应该如何有效地处理 get 和 post ?
好吧,你为什么不这样处理:
Company.js
import { merge } from 'lodash';
import axios from 'axios';
function getHeaders() {
return {
'Content-Type': 'application/json'
};
}
export class Company {
static callAPI(endpoint, extendedOptions, onSuccess, onError) {
const initalHttpData = {
method: 'GET', // By default it's GET in case you didnt specify anything
headers: getHeaders(),
url: `${API_BASE}${endpoint}`
};
// merge takes care of replacing or adding the specific key's provided via the extendedOptions
const options = merge(initalHttpData, extendedOptions);
// Fire the request for the prepared options.
let request = axios(options);
// The request once fired, needs it's success handler and error handler.
return function(dispatch) {
request
.then(response => {
dispatch({
type: onSucess,
payload: response.data
});
})
.catch(error => {
dispatch({ type: onError, payload: err});
});
}
};
}
然后我们可以使用动作专门将东西传递给这个api util:
GET API 调用:
// GET Action
export function showResultofApartment() {
return (dispatch) => {
dispatch({ type: APARTMENT_FETCH_START });
const token = localStorage.getItem('token');
// FOR GET API
return Company.callApi('/apartments', {}, APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR);
}
}
POST API 来电:
// POST Action
export function showResultOfAppartmentPost() {
return (dispatch) => {
dispatch({ type: APARTMENT_FETCH_START });
const token = localStorage.getItem('token');
// This will merge, essentially replace the method=GET once it gets called.
const extendedOptions = {
method: 'POST',
body: JSON.stringify(data),
headers: {
'X-Requested-With': 'XMLHttpRequest',
}
}
// FOR GET API
return Company.callApi('/apartments', extendedOptions, APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR);
}
因此,给出动作,定义它自己的一组 API 正文或请求。