小程序:前端防止用戶重復提交&即時消息(IM)重復發送問題解決


 

背景:

最近參與開發的小程序,涉及到即時消息(IM)發送的功能;

聊天界面如下,通過鍵盤上的【發送】按鈕,觸發消息發送功能

 

 

 

問題發現:

 功能開發完畢,進入測試流程;測試工程師反饋說:

 

在Android手機上,在極短的時間內頻繁點擊鍵盤上的【發送】按鈕,消息會重復發送;IOS上該問題不太明顯

 

本以為是普通的防重復提交問題,於是自然想到通過設定flag/js加鎖的方式解決該問題,於是開始優化代碼:

 

項目基本代碼:

 

wxml:

<input type="text" value="{{msgValue}}"  confirm-type="send" bindconfirm="sendMsg" bindinput="bindKeyInput" placeholder="請輸入聊天內容" />

  

JS:

  bindKeyInput(e) {
        this.setData({
            msgValue: e.detail.value.replace(/^\s+|\s+$/g, "")
        });
    },
    sendMsg() {
        let self = this;
        let msg = self.data.msgValue;
        if (msg && self.data.sendMsgState) {
            self.data.sendMsgState = false
            app.globalData.nim.sendText({
                scene: 'p2p',
                to: self.data.doctorId,
                text: msg,
                done(error, msg) {
                    if (!error) {
                        //消息發送成功
                        self.setData({
                            msgValue: ''
                        })
                    } else {
                        //消息發送失敗
                        wx.showToast({
                            title: '消息發送失敗,請稍后再試',
                            icon: 'none',
                            duration: 1500,
                            mask: true
                        })
                    }
                }
            })
        }
    }

  

 

1# 設定flag/js加鎖

 

//在頁面初始數據data中,聲明“鎖”: sendMsgState

data: {
    sendMsgState: true
}

//在發送消息方法中,符合消息發送條件的時候,把sendMsgState的值置為false;
//並在消息發送成功之后,將消息發送框的value置空的之后,將sendMsgState設為true
sendMsg() {
        let self = this;
        let msg = self.data.msgValue;
        if (msg && self.data.sendMsgState) {
            self.data.sendMsgState = false
            app.globalData.nim.sendText({
                scene: 'p2p',
                to: self.data.doctorId,
                text: msg,
                done(error, msg) {
                    if (!error) {
                        //消息發送成功,置空輸入框;然后把sendMsgState重新設置為true
                        self.setData({
                            msgValue: ''
                        }, () => {
                            self.data.sendMsgState = true
                        })
                    } else {
                        //消息發送失敗
                        wx.showToast({
                            title: '消息發送失敗,請稍后再試',
                            icon: 'none',
                            duration: 1500,
                            mask: true
                        })
                    }
                }
            })
        }
    }

  

測試結果:

 Android手機上依然存在該問題,且很容易復現。

 

分析原因:

在極短的時間內,頻繁點擊鍵盤上的發送按鈕;此時:鎖(sendMsgState)還沒來得及置為false,發送內容輸入框的值還沒有被清空;

但發送事件已經被有效觸發多次,導致了發送消息的重復。

 

 

2# 在方案一設定flag/js加鎖的基礎上,增加連續點擊按鈕事件間隔少於1s,或者連續兩次發送內容相同都停止發送的補充規則

 

    2.1:增加連續點擊按鈕事件間隔少於1s

             經驗證:正常的消息發送使用流程,連續兩次的消息發送間隔都是超過1s的;間隔小於1s的行為,可判定為重復提交:

            具體做法:

            步驟一:在data中注冊lastSendTime,設置值為空;觸發發送事件sendMsg的時候,把當前時間保存到變量currentTime;

      步驟二:判斷當前時間currentTime與上次發送時間的差值是否小於1000;如果是,則發送事件連續觸發時間短於1s,停止發送;

            步驟三:消息發送成功之后,在置空內容輸入框的setData回調方法中,將lastSendTime的值更新為:currentTime;

 

   2.2:如果當前發送的消息內容和上一次保存在data中的msgValue相同,則可判斷連續兩次消息重復

             因為每次發送成功,data中msg都會被置空;而內容為空的時候,又是不允許發送的;

             所以,在短時間內,如果當前發送的消息內容和上一次保存在data中的msgValue相同,則可判斷連續兩次消息重復

 

 

最終優化方案:

 

   sendMsg() {
        let self = this;
        let msg = self.data.msgValue;
        // 防止兩次點擊操作間隔太快
        let currentTime = new Date();
        if ((currentTime - this.data.lastSendTime < 1000) || (msg === self.data.msg)) {
            //發送事件連續觸發時間短於1s,或連續兩次發送內容相同,則返回
            return;
        }
        if (msg && self.data.sendMsgState) {
            self.data.sendMsgState = false
            app.globalData.nim.sendText({
                scene: 'p2p',
                to: self.data.doctorId,
                text: msg,
                done(error, msg) {
                    if (!error) {
                        self.setData({
                            msgValue: ''
                        }, () => {
                            self.data.sendMsgState = true
                            self.data.lastSendTime = currentTime
                        })
                    } else {
                        //消息發送失敗
                        wx.showToast({
                            title: '消息發送失敗,請稍后再試',
                            icon: 'none',
                            duration: 1500,
                            mask: true
                        })
                    }
                }
            })
        }
    }

  

綜上所述:

在單一的flag/js加鎖無效的情況下;通過添加額外的規則補充校驗,最終方案如下:

 

 
在發送內容msg有效及flag/js鎖為true的基礎上;
發送事件sendMsg連續兩次觸發時間間隔大於或等於1s,及連續兩次發送內容不相同的情況下,才允許消息被發送;
 

 

 

 最終測試結果:無論是Android,還是IOS都可以正常發送消息,無消息重復發送情況發生了

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM