如何处理用户的误操作引起的多次请求
北京阳光环球广告有限公司 http://www.sunad.net.cn 2018-05-09 浏览量:1000
Tags:
在互联网应用中,我们经常用到的场景,比如用户点击某个按钮,触发的操作会和后台api进行数据交互,生成一些记录,比如下单购买。如果后台api请求比较慢,而客户端体验又做得不到位,导致用户以为没点击到或者是页面假死,在上次请求还没处理完,就再次点击按钮。这样会导致某个操作生成多次记录,导致一些异常的bug。
很显然,后台的api在这方面是需要做好处理。然而,面对用户,我们需要更好的体验,可以在客户端去避免这些问题,前置地解决问题。
最近听产品经理常说,用户点击某个按钮多次,后台还没处理完导致多笔记录生成,我们需要在用户点击后跳转到一个新的页面,其实这根本不是跳页问题,是程序问题。如果程序员真这么干,是不是要下岗了。
以前偷懒的时候,在前端我们可能会这么处理:
var getUserDataFlag = false;
function getUserData() {
if (getDataFlag) {
return;
}
getDataFlag = true;
$.ajax({
url: '/xxx/getUser',
success: function () {
getUserData = false;
//todo
},
error: function () {
getUserData = false;
}
})
}
//当接口很多的时候,我们的代码就变成这样
var getUserAssetFlag = true;
function getUserAsset() {
if (getDataFlag) {
return;
}
getDataFlag = true;
$.ajax({
url: '/xxx/getUserAsset',
success: function () {
getUserAssetFlag = false;
//todo
},
error: function () {
getUserAssetFlag = false;
}
})
}
上面的例子你会发现,当接口越来越多,维护请求状态的变量将会越来越多,并且当存在依赖时,维护成本更高,也更容易出错。
如何优雅地解决这样的问题,其实封装一下请求就能简单又能自动地处理这个问题。
最近在重构angular的项目以及在写微信小程序demo,有一些小实践和总结,例子请参照原文链接https://github.com/navyxie/avoid-multi-request-from-client-。下面我们以微信小程序请求后台数据为例解说:
import {isObject} from './util'
let Promise = require('../libs/bluebird.min')
let requestList = {} //api请求记录
// 将当前请求的api记录起来
export function addRequestKey (key) {
requestList[key] = true
}
// 将请求完成的api从记录中移除
export function removeRequestKey (key) {
delete requestList[key]
}
//当前请求的api是否已有记录
export function hitRequestKey (key) {
return requestList[key]
}
// 获取串行请求的key,方便记录
export function getLockRequestKey (data) {
if (!isObject(data)) {
return data
}
let ajaxKey = 'lockRequestKey:'
try {
ajaxKey += JSON.stringify(data)
} catch (e) {
ajaxKey += data
}
return ajaxKey
}
//根据请求的地址,请求参数组装成api请求的key,方便记录
export function getRequestKey (data) {
if (!isObject(data)) {
return data
}
let ajaxKey = 'Method: ' + data.method + ',Url: ' + data.url + ',Data: '
try {
ajaxKey += JSON.stringify(data.data)
} catch (e) {
ajaxKey += data.data
}
return ajaxKey
}
//所有与服务器进行http请求的出口
export function http (data) {
if (!isObject(data)) {
throw Error('ajax请求参数必须是json对象: ' + data)
}
data.method = (data.method || 'GET').toUpperCase()
//下面5行是对所有http请求做防重复请求处理,后面单独分享原理
let ajaxKey = getRequestKey(data)
if (hitRequestKey(ajaxKey)) {
throw Error('重复提交请求:' + ajaxKey)
}
addRequestKey(ajaxKey)
//bluebird.js包装成promisepromise api
return new Promise(function (resolve, reject) {
//通过wx.request api 向服务器端发出http请求
wx.request({
url: data.url,
data: data.data,
method: data.method,
header: data.header || {'Content-Type': 'application/json'},
complete: function (res) {
// 请求完成,释放记录的key,可以发起下次请求了
removeRequestKey(ajaxKey)
let statusCode = res.statusCode
if (statusCode === 200 || statusCode === 304) {
return resolve(res.data)
}
return reject(res)
}
})
})
}
//通用get请求方法
export function httpGet (data) {
return http(data)
}
//通用post请求方法
export function httpPost (data) {
data.method = 'POST'
return http(data)
}
// 该方法适用于串行请求的api
export function lockRequest (data, fn) {
let ajaxKey = getLockRequestKey(data)
if (hitRequestKey(ajaxKey)) {
throw Error('重复提交请求:' + ajaxKey)
}
addRequestKey(ajaxKey)
return new Promise(function (resolve, reject) {
fn(data)
.then(function (data) {
removeRequestKey(ajaxKey)
return resolve(data)
})
.catch(function (error) {
removeRequestKey(ajaxKey)
return reject(error)
})
})
}
整体思路就是统一所有请求的入口,然后以API请求的地址,参数,请求类型(get,post)等组装为唯一key缓存起来。这样就能知道某个请求的完成状态,当第二个相同的请求过来时,我们可以根据上一次的状态来判断下一步的操作。
本文地址:http://www.sunad.net.cn/content-105-815-1.html
- SEO知识
- SEO热点问题
- SEO工具
- seo外链怎么优化?07-16
- 如何对网站进行seo07-15
- 有用的金融seo推广方案07-15
- seo文章关键词怎么布局才有效果07-12
- 那些与SEO相关的技术07-11
- 网站优化标题重要吗?该怎样写标题呢?07-11
- seo运营是什么意思?07-10
- 那些与SEO相关的技术07-05
- 标题在网站SEO优化中的作用是什么?07-05
- div+css为什么对网站优化有很大的帮助07-26
- SEO网站优化常犯的几种过度优化07-26
- 网站优化怎么快速找有用的分类目录07-23
- 如何找搜索引擎的高质量原创文章07-23
- 企业站如何做好seo优化工作07-10
- 北京优化公司/北京网站优化/百度权重优化到底起到多大作用07-04
- 怎样优化百度下拉框与相关搜索07-02
- 整站优化SEO/更新保护网站最好要合适的几个处理办法06-26
- seo整站优化/整站优化SEO/刚着手建时站内优化操作06-21
- SEO新手优化网站要注意的问题05-28
- 百度seo整站优化/百度SEO网站优化/网站快速排名的几种操作05-23
- SEO网站优化更新如何做软文营销07-26
- 怎么利用差别化来做网站SEO排名07-23
- 利于网站SEO迅速排名的六种实用性办法07-23
- 北京SE0网站优化/丰台SEO优化/快速排名点击小心网站被K07-04
- 关键词优化公司/百度SEO优化/操作新站SEO常见的几种不正确06-21
- SEO网站优化点击率对网站排名有多大帮助05-28
- 百度seo整站优化/百度SEO网站优化/div+css布局网站对搜索引擎的好处05-23
- 企业手机网站建设/SEO优化TDK怎么写才符合搜索引擎呢05-22
- 企业手机网站建设/企业手机站设计制作/企业手机网站建设如何提前做seo工作05-22
- SEO网站优化大神讲解网址怎样做网站优化05-21
- 建站知识
- 网站设计
- 网站开发
- 如何用最少的钱搭建一个自己的网站07-16
- 网站建设基本流程07-15
- 网站设计之首页图文混排技巧:07-12
- 网站建设小技巧提升网站质量07-11
- 影响网站建设费用的主要原因有哪几点07-10
- php秒杀系统架构设计实例07-26
- 网站建设浅谈php中使用websocket07-23
- 小白学习:网站建设登录功能讲解07-04
- 网站建设设计/网站设计/html锚点定位四种方法05-23
- 网站建设托管/网站维护托管/html select事件方法汇总05-22
- 网站建设:php 后期静态绑定07-26
- Python使用Srapy框架爬虫模拟登陆并抓取知乎内容07-23
- 网站设计功能怎样做一个简单实用的上传功能07-04
- 百度seo整站优化/百度SEO网站优化/怎样找高品质的文章进行伪原创05-23
- 网站建设托管/网站维护托管/CSS 尺寸(Dimension)05-22
- 北京企业网站建设费用报价/CSS分组和嵌套选择器05-21
- 北京手机网站制作:CSS分组和嵌套选择器05-18
- 企业网站建设/企业站定制建站/CSS padding(填充)05-17
- 北京手机网站制作/企业站定制设计/CSS margin(外边距)05-16
- 网站建设报价/网站建设费用/网站制作报价/CSS padding(填充)05-15
- 网站设计:PHPExcel导入excel文件07-26
- 最受欢迎的Python开源框架07-23
- 北京网页设计/验证邮件和URL的方法07-04
- 网站建设托管/网站维护托管/PHP 表单验证05-22
- 北京企业网站建设费用报价/PHP表单处理05-21
- 网站定制:PHP 表单处理05-18
- 企业网站建设/企业站定制建站/PHP 全局变量 - 超全局变量05-17
- 北京手机网站制作/企业站定制设计/PHP 数组排序05-16
- 网站定制设计/网站定制/网站设计/什么是数组?05-14
- 网站定制设计/网站设计定制/PHP 用户定义函数05-14
- 行业资讯
- 应用解决方案
- 你羡慕那些利用小程序赚钱的人吗?其实你也可以。07-26
- 移动端网站开发如何做代码适配?05-22
- 手机企业站定制建站设计/APP启动页面也是APP引导页面吗05-21
- APP小程序中UI界面设计需要注意的问题05-18
- 手机APP小程序开发/手机app制作公司/APP开发的几点启蒙05-17
- APP小程序开发中经常碰到的误区05-16
- APP怎样设计用户体验05-14
- APP小程序怎么不让客户卸载05-14
- 分析用户不同生命周期阶段的最基本的指标05-11
- 利于手机app开发人员了解应用程序的性能05-11
- 抖音海外版遭封禁,小程序服务暂停,近期抖音可谓是多灾多难07-26
- 如何在博客 论坛做外部链接?05-22
- 手机企业站定制建站设计/物业APP开发需要功能有哪些05-21
- APP小程序开发中手指触发尺寸怎么设置05-18
- APP小程序怎样写运营方案05-14
- APP小程序怎样推广05-14
- APP程序怎样更好的运营05-11
- APP开发中的搜索功能的设计05-11
- 小程序使用第三方模块Underscore.js,Immutable.js,UUID05-09
- 如何处理用户的误操作引起的多次请求05-09