在目前前后端分离的工作模式下,前端需要对接许多接口服务,对接的同时我们会发现很多时候会对请求做一些相同的处理,例如 阻止重复提交、根据服务的返回给前台一些相同的提示信息 或者 打印请求日志 等等。针对这种情况,我们可以通过简单的二次封装 http 请求方法,来简化我们的工作 并提高用户体验。
下面分别列举了 卡萨帝商城、海贝商城管理后台 和 数据中心 三个不同框架中对于 http 请求的实际应用,每个项目中封装的侧重点不同,但是不同框架处理问题的思路是基本一致的。
jQuery
需求: 部分服务需要校验用户登录,如未登录则应中止请求,跳转登陆页或给出提示
解决方法:设置拦截器
jQuery.ajaxSetup({
type
:
"post"
,
dataType
:
"json"
,
cache
:
false
,
box_obj
:
null
,
scroll
:
null
,
beforeSend
:
function
(request) {
// 创建一个拦截器,在请求发送出去之前做一次处理
// 判断用户是否登录,未登录则中止请求 并跳转登陆页或给出提示
if
(
this
.login && !istrsidssdssotoken()) { request.abort(); } },
success
:
function
(data) {
// 请求成功返回后可做统一处理,例如统一的弹层提示等
if
(data.isSuccess) { }
// 执行每个请求的 success_cb 方法,并传递请求的返回结果
if
(
this
.success_cb) {
this
.success_cb(data); } },
error
:
function
(jqXHR, textStatus, errorThrown) { }});
$.ajax({
url
: url,
data
: params,
login
:
true
,
// 如果设置 login 为 true 则在请求前做登录校验
success_cb:
function
(data) {
// 当前请求的成功回调
if
(data.isSuccess) {}}});
AngularJS
需求:阻止重复提交,根据后台返回做某些统一处理
解决方法:记录每次发送的请求发送前校验,同一
url
请求是否在进行中 以及 请求参数是否一致
app.factory(
'trsGetData'
,
function
($http, $q, ngDialog, $state, $rootScope, $timeout, $httpParamSerializerJQLike,siteInfo) { $rootScope.repeatedlyClick = {};
//阻止重复提交
return
function
(url, params, funName, method) {
if
(!funName) { funName =
"temporary"
; }
// 如果是下载,则走单独逻辑
if
(method ==
"download"
) { url = url +
'?'
;
for
(
var
param
in
params) {
if
(params[param]) { url += param +
'='
+ params[param] +
'&'
; } } url = url.slice(0, -1); window.location.href = url;
return
false
; }
if
(method !=
"get"
) { method =
"post"
; }
var
defer = $q.defer();
/** * 阻止重复提交 校验方法名和请求参数 */
if
(!$rootScope.repeatedlyClick[funName] || $rootScope.repeatedlyClick[funName] !== JSON.stringify(params)) { $rootScope.repeatedlyClick[funName] = JSON.stringify(params);
//记录方法funName提交的参数parms如果提交的参数相同则不会再次提交
$http({
method
: method,
url
: url,
headers
: {
'formdata'
:
"1"
,
//用于wcm解析data
'Content-Type'
:
'application/x-www-form-urlencoded;charset=UTF-8'
,
'siteId'
:siteInfo.curSite.siteId },
data
: method ==
'get'
?
""
: $httpParamSerializerJQLike(params),
params
: method ==
'get'
? params :
""
,
timeout
: 60000
//超时时间30s
}).success(
function
(data, status, headers, config) { $rootScope.repeatedlyClick[funName] =
false
;
/** * wcm登陆失败则跳转登陆页 * open服务 wcm未登录,请登录后再操作 * here应用 access-denied * wcm服务 boolean */
if
((data.resultMsg ===
"wcm未登录,请登录后再操作"
|| data.resultMsg ===
"access-denied"
|| headers(
"TRSNotLogin"
))) { $rootScope.$emit(
"userIntercepted"
,
"notLogin"
, data); }
if
(!data.isSuccess || data.isSuccess ==
'false'
) {
if
(data.resultMsg) { console.warn(data.resultMsg); } } defer.resolve(data); }).error(
function
(data, status, headers, config) { $rootScope.repeatedlyClick[funName] =
false
;
/** * 请求失败 则给出提示 */
if
(status == -1 || status == 408) { } ngDialog.open({
template
:
'common/404/dialog404.html'
,
className
:
'ngdialog-theme-default'
,
width
: 572,
showClose
:
false
,
closeByDocument
:
false
,
closeByEscape
:
false
,
controller
: [
'$scope'
,
function
($scope, $state) { $scope.dialog = {
"dialogTitle"
:
"提示"
,
"dialogMessage"
:
""
,
"dialogIcon"
:
"icon-cuowu"
,
"dialogConfirm"
:
"确定"
,
// "dialogCancel": "取消",
"goHome"
:
function
() { ngDialog.close(); },
"goBack"
:
function
() { history.go(-1); ngDialog.close(); } }; }] }); defer.reject(data); }); }
return
defer.promise; }; });
trsGetData(envUrl +
'/eshop/eshopcenter.do'
, params,
"isSiteHaveRight"
,
"post"
);
Vue.js
需求:由于列表服务返回很慢,用户如果切换不同检索条件检索的话,有可能出现后请求的数据先返回,先请求的数据后返回的情况,导致页面展示数据与用户检索条件不符的情况
解决方法:相同的请求发出前设置拦截器取消正在进行中的相同请求
var
promiseArr = {}trsGetData:
function
() {
let
cancel
// 创建 http 请求
const
httpServer = axios.create({
responseType
:
'json'
,
cancelToken
:
new
axios.CancelToken(
function
(c) { cancel = c }) }) httpServer.interceptors.request.use(
function
(config) {
if
(promiseArr[config.url]) { promiseArr[config.url](
'操作取消'
)
// 取消相同请求
promiseArr[config.url] = cancel }
else
{ promiseArr[config.url] = cancel
// 记录当前请求的 cancel 方法
}
return
config },
function
(err) {
// return Promise.reject (error)
})
return
httpServer }
gUtils.trsGetData().post(Vue.prototype.apiUrl +
'vipcenter/memberRights/query'
, data) .then(
function
(data) {
if
(data.data.isSuccess) {
return
data.data.data }
else
{
return
[] } }).catch(
function
(err) { console.warn(err)
return
catchMessage(err) }) }