加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ajax 源码解读之如何扩展 ajax 的功能

发布时间:2020-12-16 01:41:28 所属栏目:百科 来源:网络整理
导读:需求场景:借助 ajaxTransport 来自定义扩展功能。 项目需求:jQuery 版本: 1.10.2,错误打点,发起 jsonp 请求发生错误的时候前端需要向打点地址发送一个请求。 简单演示: 测试代码: $.ajax('http://google.com/a.js',{ type: 'GET',dataType: 'jsonp',s

需求场景:借助 ajaxTransport 来自定义扩展功能。

  1. 项目需求:jQuery 版本: 1.10.2,错误打点,发起 jsonp 请求发生错误的时候前端需要向打点地址发送一个请求。

  2. 简单演示:
    测试代码:

    $.ajax('http://google.com/a.js',{
           type: 'GET',dataType: 'jsonp',success: function(success,statusText,jqXHR){
               console.log('jsonp request success');
           },error: function(jqXHR,error){
               console.log('jsonp error');
           }
       });
       
       由于 1.10.2 版本的 jquery 并没有对创建的 script 监听错误事件,故无法调用 error 方法,故无法进一步将前端信息错误上报

    解决方案:

    $.ajaxTransport('+script',function(s){
           // This transport only deals with cross domain requests
           var script,head = document.head || $('head')[0] || document.documentElement;
                
           return {
               send: function(_,callback) {
                   
                   script = document.createElement('script');
                   
                   script.async = true;
                   
                   if(s.scriptCharset){
                       script.charset = s.scriptCharset;
                   }
                   
                   script.src = s.url;
                   
                   // Handle error
                   script.onerror = function(err){
                       // Handle memory lead in IE
                       script.onload = script.onreadystatechange = null;
                       script.onerror = null;
                       
                       // Remove the script
                       if(script.parentNode){
                           script.parentnode.removeChild(script);
                       }
                       
                       // Dereference the script
                       script = null;
                       
                       if(err.type === 'error'){
                           callback(404,err.type);
                       }
                   }
                   
                   // Attach handlers for all browsers
                   script.onload = script.onreadystatechange = function(_,isAbort){
                       
                       if(isAbort || !script.readyState || 
                       /loaded|complete/.test(script.readyState)){
                           // Handle memeory leak in IE
                           script.onload = script.onreadystatechange = null;
                           
                           // Remove the script
                           if(script.parentNode){
                               script.parentNode.removeChild(script);
                           }
                           
                           // Dereference the script
                           script = null;
                           
                           // Callback if not abort
                           if(!isAbort){
                               callback(200,'success');
                           }
                       }
                   };
                   
                   // Cicumvent IE6 bugs with base elements (#2709 and #4378) by prepending
                   // Use native DOM manipulation to avoid our domManip AJAX trickery
                   head.insertBefore(script,head.firstChild);
               },abort: function(){
                   if(script){
                       script.onload(undefined,true);
                   }
               }
           };
       });

需求场景:借助 ajaxSetup 新增 dataType.

  1. 项目需求:需要从服务器获取 yaml 文件,然后解析该文件

  2. 简单演示:
    解决方案:

    function parseYaml(text){
           console.log('You are parsing yaml file!');
           return 'yaml' + text + 'yaml';
       }
       $.ajaxSetup({
           accepts: {
               yaml: 'application/x-yaml,text/yaml'
           },contents: {
               yaml: /yaml/
           },converters: {
               'text yaml': function(text){
                   return parseYaml(text);
               }
           }
       });

    测试代码:

    // 发送 dataType 为 yaml 的请求
       $.ajax({
           url: 'http://google.com/helloworld.yaml',dataType: 'yaml',success: function(data){
               console.log(data);
           }
       });

需求场景:借助 ajaxPrefilter 来自定义扩展功能。

  1. 项目需求:防止 ajax 请求的重复提交

  2. 简单演示:
    解决方案:
    var pendingRequests = {};

    function storePendingRequest(key,jqXHR){

    pendingRequests[key] = true;
       jqXHR.pendingRequestKey = key;

    }

    function generatePendingRequestKey(options){

    return (options.type + options.url + options.dataType).toLowerCase().replace(/[^a-z0-9]/g,'');

    }
    $.ajaxPrefilter(function( options,originalOptions,jqXHR ) {

    // 不重复发送相同请求
       var key = generatePendingRequestKey(options);
       if (!pendingRequests[key]) {
           storePendingRequest(key,jqXHR);
       } else {
           // or do other
           jqXHR.abort();
       }
       
       var complete = options.complete;
       options.complete = function(jqXHR,textStatus) {
           // clear from pending requests
           pendingRequests[jqXHR.pendingRequestKey] = null;
           
           if ($.isFunction(complete)) {
               complete.apply(this,arguments);
           }
       };

    });

    测试代码:
    for(var i = 0; i < 10; i++){

    var j = 0;
       $.ajax({
           url: 'http://js.passport.qihucdn.com/5.0.2.js',type: 'GET',dataType: 'HTML',complete: function(){
               console.log('complete:' + j++);
           }
       });

    }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读