js 请求异常重连或断线后联网重连机制(ajax)

    这个需求的应用场景是这样的,在开发一个基于h5的移动app 时,在请求api 时出现请求的异常或者是请求中途网络中断的情况,一旦出现问题则需要重新触发某个点击事件或者打开某个页面。于是就想,遇到异常情况我们能不能让请求自动重连,重新调用我们的数据。当然,一开始都是先看看网上的解决方案,但是找了好久没找到合适的(也可能是自己没找对关键词,当时搜索的是 “js断网重连机制”)。既然没有的话,就只好自己试一下了(要是哪位朋友有解决方案,希望可以分享一下)。

    简单的整理一下需要的流程:

    >发起请求

    >如果请求正常,判断是否是期望的结果(这里说一下,一般我们的app 可以直接接我们开发的 后台 api,但是在做这个项目时有点不一样,在app与api之间多了一个第三方,我们的请求需要请求到第三方(jsp程序),然后第三方再请求我们的真实接口,有点绕,不能代理,第三方在请求异常或者超时时也有他们自己的消息返回,所以要做好判断是否是我们的数据)

        >如果数据是我们能 api 返回的 执行 ajax 回调程序

        >如果数据是第三方的异常数据  尝试重连(我们的 api 没问题的话,重新请求一般都是能得到数据的)

    >如果请求异常 尝试重连


    思路是这样,但具体实现还是有其它问题的。比如

    1. 怎么确认是哪个请求出异常并对该请求重连呢?

    2.重连的回调能否正常执行呢?

    

    暂时不管上面两个问题,本文的解决发难如下

   >建立一个 temp 数组来保存请求的记录,每一个调用 ajax 请求前都保存好必要信息:id(请求标识,标识不同的请求),url,data,callback,reloadtimes(重复请求次数) 。

    >在请求进来时,判断是否已经在 temp中,不在的话,先保存到temp 中

    >请求正常的话 从 temp 中移除

    >请求异常的话,尝试重连

    前面说了这么多,还是看看代码吧。

(function(window) {

        var temp = new Array();

        function removeTemp(obj) {
            var id = obj.id;
            //将请求记录从 temp 中去掉
            for (var key in temp) {
                if (id == temp[key].id) {
                    console.log("移除:" + temp[key].id);
                    temp.slice(key, 1);
                    break;
                }
            }
        }

        function reconnect(obj) {
            var id = obj.id;
            //这可以写更多的重连逻辑,比如 每次重连间隔的时间增加
            if (obj.reloadtimes == 10) {
                //将请求记录从 temp 中去掉
                removeTemp(obj);
            } else {
                obj.reloadtimes++;
                console.log(obj.id + " " + obj.reloadtimes + " 秒 后自动重新链接");
                setTimeout(() => {
                    request(obj.id, obj.url, obj.data, obj.callback);
                }, obj.reloadtimes * 1000); //每次间隔时间递增
            }
        }
        //请求
        function request(id, url, data, callback) {
            let obj = {
                id: id,
                url: url,
                data: data,
                callback: callback,
                reloadtimes: 0
            };
            //判断是否已经存在 缓存中了,存在则跳过
            let exist = false;
            for (let key in temp) {
                if (id == temp[key].id) {
                    exist = true;
                    obj = temp[key];
                    break;
                }
            }
            //不存在缓存中则插入
            if (!exist)
                temp.push(obj);

            $.get(url, data, res => {
                let _obj = obj;
                //判断正常请求是否符合预期,这里判断结果内容是否大于XXX,实际上可以看情况处理
                if (JSON.stringify(res).length > 5) {
                    //移除记录
                    removeTemp(_obj);
                    callback(res);
                } else {
                    //重连
                    reconnect(_obj);
                }
            }).error(e => {
                //重连
                let _obj = obj;
                console.log(_obj.id + " 请求异常");
                reconnect(_obj);
                //console.log(e);
            });
            //console.log(temp);
        }
        window.request = request;
    }(window))

    用的时候这样用就行了

    //请求测试
    request("aaaaaaa", "data.html", {}, res => {
        console.log(res);
    });
    request("bbbbbbbb", "data1.html", {}, res => {
        console.log(res);
    });
    request("ccccc", "data1.html", {}, res => {
        console.log(res);
    });
ps:这里的id 是随便写的 aaaaa 什么的,但实际开发的话,我们使用了 时间戳来作为id

    效果如图




然后回头看下那两个问题

1.本文是通过创建一个对象数组保存了请求的必要信息,满足请求以及回调所需参数。

2.这个一开始担心的是多页面共同调用一个请求,要是切换到另一个页面会不会有问题,经实践发现没有问题(app 用的是 Hbuilder 开发)


ps:这里处理的是 ajax请求的,但是 如果不用ajax 不知道能否实现呢?还有就是,百度pc 端检索如果断网会定期请求重连,但处理方式好像不一样,哪位朋友了解的话,希望能分享一下,谢谢啦!



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值