zoukankan      html  css  js  c++  java
  • 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对象
  • 相关阅读:
    HDOJ 2095 find your present (2)
    HDOJ 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
    九度 1337 寻找最长合法括号序列
    九度 1357 疯狂地Jobdu序列
    HDOJ 1280 前m大的数
    九度 1343 城际公路网
    九度 1347 孤岛连通工程
    HDOJ 2151 Worm
    九度 1342 寻找最长合法括号序列II
    九度 1346 会员积分排序
  • 原文地址:https://www.cnblogs.com/thonrt/p/5395718.html
Copyright © 2011-2022 走看看