• ajax请求解决方法及案例


      当前项目对用户体验的要求层出不穷,本篇通过所历项目与前辈网文日志加以记录总结。

      多个 ajax 请求的各类解决方案:同步,队列,cancel 请求,本章末尾提供 demo,或点这里

      注意:能一个 ajax 请求解决的问题绝不用两个 ajax 请求来处理,没有最好的方案,只有最合适的方案。

      需求大致分三类,13,24和5:

        1.多个 ajax 请求同时发送,相互无依赖。

        2.多个 ajax 请求互相依赖,必须有先后顺序。

        3.多个 ajax 请求被同时发送,只需要最后一个请求。

        4.多个 ajax 请求返回的是同一个数据的不同部分,我们需要在前端把这些数据组合成一个完整的数据来运用,即需要知道数据的次序来正确拼接。

        5.不同查询条件下的同一组数据,我们需要最新的一组数据。

      第 2 种 case

      应用场景:多个 ajax 请求,需要顺序执行,后一个 ajax 请求的执行参数是前一个 ajax 的结果。

      一个非常经典的例子:用户登录后我们发送一次请求得到用户的应用 ID,然后利用应用 ID 发送一次请求得到具体的应用内容。

      处理方法:

        1.利用 ajax 参数 async 设置为 false,进行同步操作(这个方法只适合同域操作,浏览器可能失去响应,体验糟糕,跨域需使用下面两种方法)

        2.利用 ajax 嵌套

        3.利用队列进行操作,jquery ajax 队列操作核心代码:

    (function ($) {
        var ajaxRequest = {};
    
        $.ajaxQueue = function (settings) {
            var options = $.extend({ className: 'DEFEARTNAME' }, $.ajaxSettings, settings);
            var _complete = options.complete;
            $.extend(options, {
                complete: function () {
                    if (_complete)
                        _complete.apply(this, arguments);
    
                    if ($(document).queue(options.className).length > 0) {
                        $(document).dequeue(options.className);
                    } else {
                        ajaxRequest[options.className] = false;
                    }
                }
            });
    
            $(document).queue(options.className, function () {
                $.ajax(options);
            });
    
            if ($(document).queue(options.className).length == 1 && !ajaxRequest[options.className]) {
                ajaxRequest[options.className] = true;
                $(document).dequeue(options.className);
            }
        };
    
    
    })(jQuery);

      第 3 种 case

      应用场景:比较典型的是 autocomplete 控件的操作,case 2 解决方案有些浪费。

      解决方法:保留最后一次请求,cancel之前的请求,代码如下:

    (function ($) {
    var jqXhr = {};
     $.ajaxSingle = function (settings) {
            var options = $.extend({ className: 'DEFEARTNAME' }, $.ajaxSettings, settings);
    
            if (jqXhr[options.className]) {
                jqXhr[options.className].abort();
            }
    
            jqXhr[options.className] = $.ajax(options);
        };
    })(jQuery);

      第 4 种 case

      如果中间某一个 ajax 没有正常返回,后面的 ajax 有不执行的风险。

      解决方法:递归,在回调函数中执行下一个 ajax,但需要做一些特别的处理。可以用闭包来记录当前是第几组的 ajax 请求,回调函数中读取。或前后端协商标识符,但一些公共接口数据不是我们能左右的。

      案例:百度地图API五:大批量多次坐标转换结果返回顺序问题

      第 5 种 case

      应用场景:选择查询条件并隔一段时间实时刷新。如实时显示地图绘制,实时图表绘制等。后面的数据要刷新前面的数据,比如状态的实时更新。

        1.更新了查询条件,中断当前所有 ajax 请求。清空 ajax 序列的数组,或定时发送请求。

        2.未更新查询条件,隔一段时间自动刷新数据,理论上我们只需要最新的一组数据。

      解决方法:设置超时,超时的时间不要超过请求的间隔。这样当发起新的 ajax 请求时,上一个 ajax 已经返回结果或者超时取消了。

           若网络条件差,超时的时间或两次 ajax 请求之间的间隔又比较短,可能一组数据都拿不下来,页面发呆。所以可不设置超时,能拿下一组数据是一组,拿到数据后再清除 ajax 序列中此请求前面的 ajax 请求或者简单中断当前所有请求的 ajax。

      资料:

        1.ajax 中断查询 abort() 方法

        2.封装error 和超时功能:封装的JSONP跨域函数    待整理。

        3.ajax 序列,即将所有的 ajax 请求放到一个数组中去,方便控制,参考:

    var xhr = $.ajax({  
                  url: '__SELF__',  
                  type: 'get',  
                  dataType: 'json',  
                  cache:false,  
                  data: {stationid: StationID  
                  },  
                  success:function(data){  
              });  
     xhrArr.push(xhr);

       

      某500强企业操作平台解决方案,待整理。

      由于多个 ajax 请求的响应时间无法控制,可以用 ?解决。完整 demo 如下:

    body:
    
    <form id="form1" runat="server">
        <input type="button" id="btnLaunchAsync" value="Launch Asynchronous Request" />
        <input type="button" id="btnLaunchSync" value="Launch Synchronous Request" />
        <input type="button" id="btnLaunchQueue" value="Launch Requested Queue" />
        <input type="button" id="btnLaunchSingle" value="Launch Single Request" />
        <div id="txtContainer"></div>
        </form>
    
    JavaScript:
    
    (function ($) {
        var jqXhr = {},
            ajaxRequest = {};
    
        $.ajaxQueue = function (settings) {
            var options = $.extend({ className: 'DEFEARTNAME' }, $.ajaxSettings, settings);
            var _complete = options.complete;
            $.extend(options, {
                complete: function () {
                    if (_complete)
                        _complete.apply(this, arguments);
    
                    if ($(document).queue(options.className).length > 0) {
                        $(document).dequeue(options.className);
                    } else {
                        ajaxRequest[options.className] = false;
                    }
                }
            });
    
            $(document).queue(options.className, function () {
                $.ajax(options);
            });
    
            if ($(document).queue(options.className).length == 1 && !ajaxRequest[options.className]) {
                ajaxRequest[options.className] = true;
                $(document).dequeue(options.className);
            }
        };
    
        $.ajaxSingle = function (settings) {
            var options = $.extend({ className: 'DEFEARTNAME' }, $.ajaxSettings, settings);
    
            if (jqXhr[options.className]) {
                jqXhr[options.className].abort();
            }
    
            jqXhr[options.className] = $.ajax(options);
        };
    
    })(jQuery);
    
    var ajaxSleep = (function () {
        var _settings = {
            type: 'GET',
            cache: false,
            success: function (msg) {
                var thtml = $('#txtContainer').html();
                $('#txtContainer').html(thtml + "<br />" + msg);
            }
        };
        return {
            get: function (seconds, mode, isAsync) {
                var mode = mode || 'ajax',
                            isAsync = isAsync || false;
    
                $[mode]($.extend(_settings, {
                    url: "ResponsePage.aspx?second=" + seconds,
                    async: isAsync,
                    className: 'GET'
                }));
            },
            post: function (seconds, mode, isAsync) {
                var mode = mode || 'ajax',
                            isAsync = isAsync || false;
    
                $[mode]($.extend(_settings, {
                    type: 'POST',
                    url: "PostPage.aspx",
                    data: { second: seconds },
                    async: isAsync,
                    className: 'POST'
                }));
            }
        };
    } ());
    
    var launch = function (settings) {
    
        $('#txtContainer').html('');
    
        var mode = settings.mode,
                    isAsync = settings.isAsync;
    
        ajaxSleep.get(12, mode, isAsync);
        ajaxSleep.get(10, mode, isAsync);
        ajaxSleep.get(8, mode, isAsync);
    
        ajaxSleep.post(6, mode, isAsync);
        ajaxSleep.post(4, mode, isAsync);
        ajaxSleep.post(2, mode, isAsync);
    }
    
    $(document).ready(function () {
        //第1种case
        $('#btnLaunchAsync').click(function () {
            launch({ isAsync: true });
        });
    
        //第2种case
        $('#btnLaunchSync').click(function () {
            launch({});
        });
    
        //第2种case
        $('#btnLaunchQueue').click(function () {
            launch({ mode: 'ajaxQueue', isAsync: true });
        });
    
        //第3种case
        $('#btnLaunchSingle').click(function () {
            launch({ mode: 'ajaxSingle', isAsync: true });
        });
    });

     

      摘自:多ajax请求的各类解决方案(同步, 队列, cancel请求)

  • 相关阅读:
    package.json中 npm依赖包版本前的符号的意义
    移动端1px的border
    react下将输入的汉字转化为拼音
    h5打开App的方法。
    图片在缩放截取后以固定尺寸上传到第三方
    图片裁切,上传,自动匹配颜色。
    ReactNative学习一
    MySQL数据库8(二)MySQL基本介绍
    MySQL数据库8(一)SQL简介

  • 原文地址:https://www.cnblogs.com/yuqlblog/p/9160287.html
Copyright © 2020-2023  润新知