注冊登錄

微信小程序開發(fā)點擊按鈕常見問題解決

2020-09-28
導讀:2017年6月14日,微信小程序開發(fā)點擊按鈕已經(jīng)是當下最熱門的話題,下面將從多方面來談微信小程序開發(fā)點擊按鈕相關(guān)的內(nèi)容。...

微信小程序開發(fā)點擊按鈕已經(jīng)是當下最熱門的話題,下面將從多方面來談微信小程序開發(fā)點擊按鈕相關(guān)的內(nèi)容。

在互聯(lián)網(wǎng)應用中,我們經(jīng)常用到的場景,比如用戶點擊某個按鈕,觸發(fā)的操作會和后臺api進行數(shù)據(jù)交互,生成一些記錄,比如下單購買。如果后臺api請求比較慢,而客戶端體驗又做得不到位,導致用戶以為沒點擊到或者是頁面假死,在上次請求還沒處理完,就再次點擊按鈕。這樣會導致某個操作生成多次記錄,導致一些異常的bug。

很顯然,后臺的api在這方面是需要做好處理。然而,面對用戶,我們需要更好的體驗,可以在客戶端去避免這些問題,前置地解決問題。

最近聽產(chǎn)品經(jīng)理常說,用戶點擊某個按鈕多次,后臺還沒處理完導致多筆記錄生成,我們需要在用戶點擊后跳轉(zhuǎn)到一個新的頁面,其實這根本不是跳頁問題,是程序問題。如果程序員真這么干,是不是要下崗了。

以前偷懶的時候,在前端我們可能會這么處理:

 

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;

   }

 })

}

 

上面的例子你會發(fā)現(xiàn),當接口越來越多,維護請求狀態(tài)的變量將會越來越多,并且當存在依賴時,維護成本更高,也更容易出錯。

如何優(yōu)雅地解決這樣的問題,其實封裝一下請求就能簡單又能自動地處理這個問題。

下面我們以微信小程序請求后臺數(shù)據(jù)為例解說:

 

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

}

 

//根據(jù)請求的地址,請求參數(shù)組裝成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

}

//所有與服務(wù)器進行http請求的出口

export function http (data) {

   if (!isObject(data)) {

       throw Error('ajax請求參數(shù)必須是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 向服務(wù)器端發(fā)出http請求

       wx.request({

           url: data.url,

           data: data.data,

           method: data.method,

           header: data.header || {'Content-Type': 'application/json'},

           complete: function (res) {

               // 請求完成,釋放記錄的key,可以發(fā)起下次請求了

               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)

           })

   })

}

 

整體思路就是統(tǒng)一所有請求的入口,然后以API請求的地址,參數(shù),請求類型(get,post)等組裝為唯一key緩存起來。這樣就能知道某個請求的完成狀態(tài),當?shù)诙€相同的請求過來時,我們可以根據(jù)上一次的狀態(tài)來判斷下一步的操作。

 


重磅推薦:小程序開店目錄

第一部分:小商店是什么

第二部分:如何開通一個小商店

第三部分:如何登錄小商店

第四部分:開店任務(wù)常見問題

第五部分:小商店可以賣什么

第六部分:HiShop小程序特色功能

第七部分:小程序直播

第八部分:小程序收貨/物流

第九部分:小程序怎么結(jié)算

第十部分:小程序客服

第十一部分:電商創(chuàng)業(yè)

第十二部分:小程序游戲開發(fā)

電話咨詢 微信咨詢 預約演示 0元開店