前端异步请求中后发先到的解决方案

通用的组件请求管理器,解决异步请求中的后发先到的问题

测试方法:可以使用fiddler进行测试,选择fiddler rules菜单中的automatic breakpoints中的afterResponse,这样可以阻止后端过快地返回,从而可以自己选择哪个请求的结果先返回,实现模拟后发先到的情况。

tips:每当需要取消之前发出的请求时,需要调用clearRequestId方法。

CommonRequestIdManager.js

/*
  通过id来跟踪请求和判断返回是否有效
*/
function CommonRequestIdManager() {
        if (!(this instanceof CommonRequestIdManager)) {
            return new CommonRequestIdManager();
        }
        this.initRequestId();
    }
    CommonRequestIdManager.prototype = {
        // id初始化
        initRequestId: function() {
          this.requestId = 0;
        },
        // 获取该次请求对应的id
        getRequestId: function() {
          return this.requestId;
        },
        // 清除请求的id,把id加一,导致前面发出的请求不可用
        clearRequestId: function() {
          return this.addRequestId();
        },
        addRequestId: function() {
          return this.requestId++;
        },
        // 获取当前的请求id
        getCurrentRequestId: function() {
          return this.getRequestId();
        },
        // 获取该次请求对应的回调
        getCb: function(cb,context) {
          var self = this;
          var requestId = this.getRequestId()
           console.log(requestId)
          return function(data) {
              // 对于返回的结果,判断回调函数绑定的id是否等于当前的请求id
              if (requestId === self.getCurrentRequestId()) {
                  cb && cb.call(context || null, data);
              }
          }
        }
    }

测试页面

<!DOCTYPE html>
<html>
<head>
    <title>my login</title>
    <script type="text/javascript" src="jquery-1.10.2.js"></script>
</head>
<script type="text/javascript" src="./CommonRequestIdManager.js">

</script>
<body>
    <input type="text" name="name">submit
    <script type="text/javascript">
        var commonRequestIdManager = new CommonRequestIdManager();
        $('input').on('keydown', function() {
            // 清除前面发出的所有请求
            commonRequestIdManager.clearRequestId();
            $.ajax({
                url: '1.php',
                success:commonRequestIdManager.getCb(function() {
                    console.log('success')
                }),
                error:commonRequestIdManager.getCb(function() {
                    console.log('error')
                })
            })
        })
    </script>
</body>

</html>

优化版本:

/*
  通过id来跟踪请求和判断返回是否有效
*/
function CommonRequestIdManager() {
        if (!(this instanceof CommonRequestIdManager)) {
            return new CommonRequestIdManager();
        }
        // 是否已經取消了請求,如果是,則新建請求之前不需要再自增requestId
        this.hasCanceled = false;
        // 是否已經發送過請求
        this.haveEverMakeRequest = false;
        this.initRequestId();
    }
    CommonRequestIdManager.prototype = {
        // id初始化
        initRequestId: function() {
          this.requestId = 1;
        },
        // 获取该次请求对应的id
        getRequestId: function() {
          return this.requestId;
        },
        // 清除请求的id,把id加一,导致前面发出的请求不可用,用於沒有發送新請求,但是通過其他操作取消了請求,比如點擊取消按鈕
        clearFormerRequest: function() {
          this.hasCanceled = true;
          this.addRequestId();  
        },
        /* 
          清除请求的id,把id加一,导致前面发出的请求不可用,用於發送新請求之前使用,
          如果已經通過其他操作取消了請求,或者還沒有發送過請求,則不需要再自增requestId。
        */
        clearFormerRequestBeforeRequest: function() {
          if (!!this.hasCanceled || !this.haveEverMakeRequest) {
            return;
          }
          return this.addRequestId();  
        },
        addRequestId: function() {
          return this.requestId++;
        },
        // 获取当前的请求id
        getCurrentRequestId: function() {
          return this.getRequestId();
        },
        // 获取该次请求对应的回调
        getCb: function(cb,context) {
          var self = this;
          var requestId = this.getRequestId();
          // 每次新發送請求之前重置標記位
          this.hasCanceled = false;
          this.haveEverMakeRequest = true;
           console.log(requestId)
          return function(data) {
              // 对于返回的结果,判断回调函数绑定的id是否等于当前的请求id
              if (requestId === self.getCurrentRequestId()) {

                  cb && cb.call(context || null, data);
              }
          }
        }
    }

在优化版本中,显式定义了两种取消请求的方法,clearFormerRequest和clearFormerRequestBeforeRequest,后者用于在发送新的请求前使用,前者是没有发送新的请求,而是通过其他操作取消了请求,比如点击取消按钮。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值