小程序:前端防止用户重复提交&即时消息(IM)重复发送问题解决

 

背景:

最近参与开发的小程序,涉及到即时消息(IM)发送的功能;

聊天界面如下,通过键盘上的【发送】按钮,触发消息发送功能

 

 

 

问题发现:

 功能开发完毕,进入测试流程;测试工程师反馈说:

 

在Android手机上,在极短的时间内频繁点击键盘上的【发送】按钮,消息会重复发送;IOS上该问题不太明显

 

本以为是普通的防重复提交问题,于是自然想到通过设定flag/js加锁的方式解决该问题,于是开始优化代码:

 

项目基本代码:

 

wxml:

1
<input type="text" value="{{msgValue}}"  confirm-type="send" bindconfirm="sendMsg" bindinput="bindKeyInput" placeholder="请输入聊天内容" />

  

JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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加锁

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//在页面初始数据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相同,则可判断连续两次消息重复

 

 

最终优化方案:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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都可以正常发送消息,无消息重复发送情况发生了

 

 

posted @   Me-Kevin  阅读(4044)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
阅读排行:
· 从零开始开发一个 MCP Server!
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
点击右上角即可分享
微信分享提示