登录/注册

首页 资讯 微信小程序开发填坑,优雅地处理用户的误操作引起的多次请求

微信小程序开发填坑,优雅地处理用户的误操作引起的多次请求

资讯来源:蜂鸟

微信小程序,开发,小应用

2020/05/12 11:15

1702

文章页标题下640*60

在互联网应用中,我们经常用到的场景,比如用户点击某个按钮,触发的操作会和后台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;

   }

 })

}


上面的例子你会发现,当接口越来越多,维护请求状态的变量将会越来越多,并且当存在依赖时,维护成本更高,也更容易出错。

如何优雅地解决这样的问题,其实封装一下请求就能简单又能自动地处理这个问题。

下面我们以微信小程序请求后台数据为例解说:


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缓存起来。这样就能知道某个请求的完成状态,当第二个相同的请求过来时,我们可以根据上一次的状态来判断下一步的操作。


文章页底部820*135

发布小程序

文章投稿

投稿邮箱:

info@appbulo.com

官方微信

扫一扫关注 小程序官方微信

新浪微博

扫一扫

( 暂不支持下载 )
PC右侧250*250

关于我们

网站简介 媒体报道

联系我们

官方微博 客服QQ:1763425497

我们的产品

多商户分销商城 本地城市生活圈
扫码浏览手机版
© 版权所有 河源市城市互动科技有限公司 [ 小程序部落 ] 微信小程序导航站 排行榜 小程序商店 资讯 专题 评测 排行服务 站务邮箱:8462482@QQ.com 技术支持:城市互动 粤ICP备14002524号