• Jquery 实现原理之 Ajax


    一:Jquery Ajax底层接口有$.ajaxPrefilters、$.ajaxTransport、$.ajaxSettings、$ajaxSetup、$ajaxSettings;

      其中$.ajaxPrefilters $.ajaxTransport是通过inspectPrefiltersOrTransports构造器来创建的;

    $.ajaxPrefilters:是一个前置过滤器,在每个请求被$.ajaxTransport()和$.ajax()处理之前调用,设置自定义ajax选项或者修改现有的选项,简单说就是hack的  做法,但是比事件处理的hack的手法更加高明。可以用来处理参数,注册回调等。

    例如:改变代理服务器的域请求

    1 $.ajaxPrefilter("+*", function( options ) {
    2   if ( options.crossDomain ) {
    3     options.url = "http://mydomain.net/proxy/" + encodeURIComponent( options.url );
    4     options.crossDomain = false;
    5   }
    6 });

    $.ajaxTransport:是一个请求分发器,是发送请求的具体实现,比如xhr就用xmlhttprequest来实现,script就是通过head中插入script标签来实现.

    例如:用来拦截发送的请求

     1 $.ajaxTransport("+*", function(options, originalOptions, jqXHR) {
     2         return {
     3             send: function(headers, completeCallback) {
     4                 var status = 404;
     5                 var statusText = "error";
     6                 var response = {
     7                     text: ""
     8                 };
     9                 var item = {            
    10                     url: "/paapi/v1/datapoints/pa",
    11                     data: data.groupsdatapoint
    12                 };
    13                 if (!item) {
    14                     console.log("require mock data: 
    " + originalOptions.url);
    15                 } else {
    16                     status = 200;
    17                     statusText = "ok";
    18                     var data = item.data;
    19                     response.text = data;
    20                 }
    21                 setTimeout(function() {
    22                     completeCallback(status, statusText, response);
    23                 }, 0);
    24             }
    25         };
    26     });

    二: ajax的实现

      实现ajax的目的是什么?

    实现ajax的目的主要是对不同的dataType的具体处理和实现,比如'jsonp'应该怎么处理,'script'怎么处理,'*'怎么处理;

    对此ajax模块的做法是,提供一个基本的模块ajax,然后通过插件形式来实现对不同dataType的处理。

    ajax暴露ajaxPrefilter: addToPrefiltersOrTransports( prefilters ) , ajaxTransport: addToPrefiltersOrTransports( transports )是给插件用的,可以注册自己的dataType处理函数。

    其中prefilters={'jsonp': function() {}, '*': function(){}, 'script':function(){}}可能是这样的,ajax在每个请求发送之前,根据dataType调用prefilters中的函数进行预处理,然后调用transport中的对应函数来发送请求。

    addToPrefiltersOrTransports()方法如下:

     1 function addToPrefiltersOrTransports(structure) {
     2 
     3      // dataTypeExpression is optional and defaults to "*"
     4      return function(dataTypeExpression, func) {
     5 
     6           if (typeof dataTypeExpression !== "string") {
     7                func = dataTypeExpression;
     8                dataTypeExpression = "*";
     9           }
    10 
    11           var dataType,
    12                i = 0,
    13                dataTypes = dataTypeExpression.toLowerCase().match(rnotwhite) || [];
    14 
    15           if (jQuery.isFunction(func)) {
    16                // For each dataType in the dataTypeExpression
    17                while ((dataType = dataTypes[i++])) {
    18                     // Prepend if requested
    19                     if (dataType[0] === "+") {
    20                          dataType = dataType.slice(1) || "*";
    21                          (structure[dataType] = structure[dataType] || []).unshift(func);
    22 
    23                          // Otherwise append
    24                     } else {
    25                          (structure[dataType] = structure[dataType] || []).push(func);
    26                     }
    27                }
    28           }
    29      };
    30 }

    该函数功能就是把某一个dataType对应的处理函数func存进structure中,实际就是一个简单的注册事件。

     1 // Base inspection function for prefilters and transports
     2 function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR) {
     3 
     4      var inspected = {},
     5           seekingTransport = (structure === transports);
     6 
     7      function inspect(dataType) {
     8           var selected;
     9           inspected[dataType] = true;
    10           jQuery.each(structure[dataType] || [], function(_, prefilterOrFactory) {
    11                var dataTypeOrTransport = prefilterOrFactory(options, originalOptions, jqXHR);
    12                if (typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[dataTypeOrTransport]) {
    13                     options.dataTypes.unshift(dataTypeOrTransport);
    14                     inspect(dataTypeOrTransport);
    15                     return false;
    16                } else if (seekingTransport) {
    17                     return !(selected = dataTypeOrTransport);
    18                }
    19           });
    20           return selected;
    21      }
    22 
    23      return inspect(options.dataTypes[0]) || !inspected["*"] && inspect("*");
    24 }
    25 }

    该代码时取调用dataType对应的prefilters和transports函数而已。

    Ajax完成一部请求的全过程:

    • 创建了一个jqXHR对象,这个对象就是ajax的返回值
    • 用deferred对象封装jqXHR对象,因此可以实现链式的异步操作:xhr.complete(x).success(x).errorl(x),这里的complete,success和error就是promise对象的add, done和fail的别名而已。
    • 调用函数inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ),那些插件注册的prefilters函数就在这里被调用了。
    • 做了一大对后续的处理,比如设置header参数,设置缓存cache
    • 调用inspectPrefiltersOrTransports( transports, s, options, jqXHR )函数发送请求
    • 定义了done函数,当请求发送结束之后做后续处理,包括调用convert转换结果、设置statusText,调用deferred.resolveWith触发异步回调等
    • 最后返回了jqXHR对象
  • 相关阅读:
    Hi35XXX海思媒体处理平台架构介绍(转)
    STM32F103步进电机梯形匀加速算法(转)
    STM32+ESP8266通过AT指令WIFI连接阿里云MQTT服务器(转)
    ESP8266 WIFI串口通信模块使用详解(转)
    UCGUI字体研究(转)
    用STM32制作汽车蓝牙OBD转速/车速表(带LED转速指示)(转)
    用STM32制作汽车蓝牙OBD转速/车速表(带LED转速指示)(转)
    接口测试框架接入性能测试实践分享
    超全Python IDE武器库大总结,优缺点一目了然!
    推荐一款万能抓包神器:Fiddler Everywhere
  • 原文地址:https://www.cnblogs.com/thonrt/p/5395718.html
Copyright © 2020-2023  润新知