jQuery deferred应用之ajax详细源码分析(二)
在上一节中,我只贴出了$.Deferred的源码分析,并没用讲解怎么使用它,现在我们先看看$.ajax是如何使用它,让我们进行异步任务的处理。
如果没看上节的代码,请先稍微了解一下jQuery Deferred的工作原理,这样ajax你才能用得更好。
这里我将以一个跨域请求 "http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"这个js文件为例,讲解jQuery的ajax工作原理,知道了原理,什么ajax都是浮云了。
先看这张图片,对$.ajax先来看全局的展望

这里外部有两个变量 prefilters = {}, transports = {}, 他们将会应为addToPrefiltersOrTransports() 通过闭包变为
prefilters={json:[fun],jsonp:[fun],script:[fun]} transports={*:[fun],script:[fun]} 这里先不讨论这两个变量,我们这次用实例开始吧
  var req = $.ajax("http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js", 
  { dataType: "script", cache: true, timeout: "10000", statusCode: {200: function () { console.log("request finished and response is ready") }, 
   0: function () { console.log("request wrong")} } }).done(function () { console.log("跨域请求成功") }).success(function () { console.log("跨域请求成功2") });;
        req.done(function () { console.log("跨域请求成功3") });
这里,设置跨域请求js文件,简单的参数配置,前面说过jQuery ajax有强大的ajaxSettings参数配置,这里为什么$.ajax().done().success()呢?其实这个$.ajax()会返回一个jqXHR,然后这个对象
因为这句代码deferred.promise(jqXHR),使得jqXHR具有deferred对象的所有只读方法。详情见上章,接下来一步步看这个代码如何执行.
 ajax: function (url, options) {
            //如果url是对象的话,冒充1.5版本之前的方法                 -->$.ajax({url:"xx",data:{},})
            if (typeof url === "object") {
                options = url;
                url = undefined;
            }
            //强制设置options成为一个对象                           -->options为对象
            options = options || {};                       
            //这里创建了ajax的很多私有变量
            var //创建最终的ajax参数对象s
            s = jQuery.ajaxSetup({}, options),                     -->通过$.ajaxSetup改变默认的参数配置,返回给s. 
            // Callbacks context
            callbackContext = s.context || s,
            // Context for global events
            // It's the callbackContext if one was provided in the options
            //如果是Dom node或者jQuery collection
            globalEventContext = callbackContext !== s &&
                (callbackContext.nodeType || callbackContext instanceof jQuery) ?
                        jQuery(callbackContext) : jQuery.event,
            // 创建一个deferred对象
            deferred = jQuery.Deferred(),                                             -->使用到了Deferred对象
            completeDeferred = jQuery._Deferred(),
            // Status-dependent callbacks
            //一组数值的HTTP代码和函数对象,当响应时调用了相应的代码 如$.ajax({statusCode: {404: function() {alert('page not found');}});
              默认为空对象
            statusCode = s.statusCode || {},                                -->这里我们传了一个 statusCode:{200:function(){}..}
            // ifModified key
            ifModifiedKey,
            // 请求头部 (they are sent all at once)
            requestHeaders = {},
            requestHeadersNames = {},
            // 响应 headers
            responseHeadersString,
            responseHeaders,
            // transport
            transport,
            //请求超时时间,异步请求下请求多少时间后中止请求,
            timeoutTimer,                                                  -->timeout:10000
            // 判断是否是跨域请求的变量
            parts,
            // jqXHR state
            state = 0,
            // To know if global events are to be dispatched
            fireGlobals,
            // Loop variable
            i,
            //伪劣的jqXHR,                                                    -->这里就是返回的jqXHR对象,初始一些key
            jqXHR = {
                readyState: 0,
                /*设置dataType,达到预期服务器返回的数据类型,,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断
                */
                setRequestHeader: function (name, value) {
                    //这里状态还为0,表示还在发送请求前,设置请求头
                    if (!state) {
                        var lname = name.toLowerCase();
                        name = requestHeadersNames[lname] = requestHeadersNames[lname] || name;
                        requestHeaders[name] = value; //私有requestHeadersNames
                    }
                    return this;
                },
                // Raw string
                getAllResponseHeaders: function () {
                    return state === 2 ? responseHeadersString : null;
                },
                // Builds headers hashtable if needed
                getResponseHeader: function (key) {
                    var match;
                    if (state === 2) {
                        if (!responseHeaders) {
                            responseHeaders = {};
                            while ((match = rheaders.exec(responseHeadersString))) {
                                responseHeaders[match[1].toLowerCase()] = match[2];
                            }
                        }
                        match = responseHeaders[key.toLowerCase()];
                    }
                    return match === undefined ? null : match;
                },
                // Overrides response content-type header
                overrideMimeType: function (type) {
                    if (!state) {
                        s.mimeType = type;
                    }
                    return this;
                },
                // Cancel the request
                abort: function (statusText) {
                    statusText = statusText || "abort";
                    if (transport) {
                        transport.abort(statusText);
                    }
                    done(0, statusText);
                    return this;
                }
            };
            /* Callback for when everything is done, jQuery作者喜欢函数里嵌套函数,局部调用方便
            * 2: request received 
            * 4: request finished and response is ready   <---readyState                
            * 200: "OK"
            * 404: Page not found                         <----status
            */
            function done(status, nativeStatusText, responses, headers) {      -->这个done函数写到这个函数的内部,处理不同状态的req,
                                                                                 其实这个写法改成var done=function(){}更好   
                // 请求状态为2,表面已经请求过一次,立即返回                          -->我是分析到下面回来的 ,第一次请求默认的state=0
                if (state === 2) {
                    return;
                }
                // State is "done" now
                state = 2;                                         -->哦,处理了,为什么是2呢,因为XMLHttpRequest 状态为2的意思是
                                                                               request received
                // 如果存在超时请求中止,清楚这个timeout
                if (timeoutTimer) {                                      -->timeout有用了,这里被清除了~_~,我都响应请求了,肯定得把你删了
                    clearTimeout(timeoutTimer);
                }
                // Dereference transport for early garbage collection
                // (no matter how long the jqXHR object will be used)
                transport = undefined;
                // Cache response headers
                responseHeadersString = headers || "";
                // Set readyState
                jqXHR.readyState = status > 0 ? 4 : 0;                                              
                var isSuccess,
            success,
            error,
            statusText = nativeStatusText,
            response = responses ? ajaxHandleResponses(s, jqXHR, responses) : undefined,
            lastModified,
            etag;
                // If successful, handle type chaining
                if (status >= 200 && status < 300 || status === 304) {                            -->服务器成功处理了 我们的状态是200
                    // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
                    if (s.ifModified) {
                        if ((lastModified = jqXHR.getResponseHeader("Last-Modified"))) {
                            jQuery.lastModified[ifModifiedKey] = lastModified;
                        }
                        if ((etag = jqXHR.getResponseHeader("Etag"))) {
                            jQuery.etag[ifModifiedKey] = etag;
                        }
                    }
                    // If not modified
                    if (status === 304) {
                        statusText = "notmodified";
                        isSuccess = true;
                        // If we have data
                    } else {          
                        try {
                            success = ajaxConvert(s, response);                           --> 200状态,isSucess=true
                            statusText = "success";
                            isSuccess = true;
                        } catch (e) {
                            // We have a parsererror
                            statusText = "parsererror";
                            error = e;
                        }
                    }
                } else {
                    // We extract error from statusText
                    // then normalize statusText and status for non-aborts
                    error = statusText;
                    if (!statusText || status) {
                        statusText = "error";
                        if (status < 0) {
                            status = 0;
                        }
                    }
                }
                //设置jqXHR.status 其实也就是XMLHttpRequest状态
                jqXHR.status = status;                                                      -->哦,这里设置了jqXHR的状态了 200
                jqXHR.statusText = "" + (nativeStatusText || statusText);
                // 成功请求 resolveWith
                if (isSuccess) {                                                             
                    deferred.resolveWith(callbackContext, [success, statusText, jqXHR]); 
                                                                 ->成功了,当然得resolveWith,是不是发现done或者
                                                                     success进来的函数一个个执行了^_^
                } else {  //失败请求 rejectWith                                  
                                                    ->resolve意味着什么?意味后面不管你done().done() 多少都会被直接触发 ~_~
                    deferred.rejectWith(callbackContext, [jqXHR, statusText, error]);               
                }
                // 状态参数代码,默认为空                                                             
                jqXHR.statusCode(statusCode);
                statusCode = undefined;
                if (fireGlobals) {
                    globalEventContext.trigger("ajax" + (isSuccess ? "Success" : "Error"),
            [jqXHR, s, isSuccess ? success : error]);
                }
                // 不管请求成功与否都执行的complete  resolveWith
                completeDeferred.resolveWith(callbackContext, [jqXHR, statusText]);     
                                                        -->原来$.ajax().complete在这里调用,所以不管成功没有都resolve了
                if (fireGlobals) {
                    globalEventContext.trigger("ajaxComplete", [jqXHR, s]);
                    // Handle the global AJAX counter
                    if (!(--jQuery.active)) {
                        jQuery.event.trigger("ajaxStop");
                    }
                }
            }
            // 给这个jqXHR对象附上deferred对象的只读方法,包括done,always,isResolved等等,这里表明了,为什么$.ajax过后
            //我们可以使用sucess,error,complete方法
            deferred.promise(jqXHR);
            jqXHR.success = jqXHR.done;                        -->作者为了让我们更好的调用,又多了3个借口,哎,其实可以直接不需要的
            jqXHR.error = jqXHR.fail;
            jqXHR.complete = completeDeferred.done;
            // Status-dependent callbacks 其实这个参数变量很少用,不过还可以,目前可以触发两个状态的statusCode: {200: function ()                       
              //{ console.log("request ok") }, 404: function () { console.log("page not found")} }
            jqXHR.statusCode = function (map) {                                                          --> map={200:"..",0:".."}
                if (map) {
                    var tmp;  //临时函数变量
                    if (state < 2) {
                        for (tmp in map) {
                            statusCode[tmp] = [statusCode[tmp], map[tmp]];
                        }
                    } else {
                        tmp = map[jqXHR.status]; //jqXHR返回相应的callback,然后调用then方法触发    
                                                                     --> 我们的状态代码在这里调用,通过jqXHR.then方法调用
                        jqXHR.then(tmp, tmp);
                    }
                }
                return this;
            };
            // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
            // We also use the url parameter if available
            //  Remove 将url的hash去掉 rhash=/#.*$/ rprotocol = /^\/\//  ajaxLocParts[1]="http:"
            s.url = ((url || s.url) + "").replace(rhash, "").replace(rprotocol, ajaxLocParts[1] + "//");
            // 取出dataTypes list,不存在则为*  rspacesAjax = /\s+/ 如:s.dataType=[*]
            s.dataTypes = jQuery.trim(s.dataType || "*").toLowerCase().split(rspacesAjax);
            //默认设置crossDomain 同域请求为false, 跨域请求为true,如果想强制跨域请求(如JSONP形式)同一域,设置crossDomain为true
            if (s.crossDomain == null) {
                //同ajaxLocParts变量,这里也是通过这个请求的url来判断是否是跨域请求
                parts = rurl.exec(s.url.toLowerCase());
                //这里来判断是否是跨域请求,又是!! 主要判断请求的url parts与 ajaxLocParts      -->这里智能判断你的请求地址是否是跨越,很
                                                                                         牛气吧,这里我们的corssDomain为true
                s.crossDomain = !!(parts &&
            (parts[1] != ajaxLocParts[1] || parts[2] != ajaxLocParts[2] ||
            (parts[3] || (parts[1] === "http:" ? 80 : 443)) !=
            (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? 80 : 443)))
            );
            }
            //如果存在data参数并且 processData=true&&s.data为一个对象吧           -->我们没传data参数,processData参数默认为true,
                                                                                  表示默认序列化参数data
            if (s.data && s.processData && typeof s.data !== "string") {
                //调用序列化函数
                s.data = jQuery.param(s.data, s.traditional);
            }
            // Apply prefilters
            inspectPrefiltersOrTransports(prefilters, s, options, jqXHR);                     -->发送请求前,调用过滤器将      
            // If request was aborted inside a prefiler, stop there
            if (state === 2) {
                return false;
            }
            // We can fire global events as of now if asked to
            fireGlobals = s.global;
            // Uppercase the type
            s.type = s.type.toUpperCase();
            // Determine if request has content
            //rnoContent= /^(?:GET|HEAD)$/
            s.hasContent = !rnoContent.test(s.type);
            // Watch for a new set of requests
            if (fireGlobals && jQuery.active++ === 0) {
                jQuery.event.trigger("ajaxStart");
            }
            // More options handling for requests with no content
            if (!s.hasContent) {
                //如果data参数存在,则append to url
                if (s.data) {                                               -->我们以前是不是喜欢xx.php?data="xx"&&.. 这里会把序列化
                                                                                后的data传到问号后面,很简单吧  
                    //rquery = /\?/请求的url是否存在"?" 就比如请求"user.php?"    -->这就是为什么data参数会被传到url?后面
                    s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
                    // #9682: remove data so that it's not used in an eventual retry
                    delete s.data;
                }
                // Get ifModifiedKey before adding the anti-cache parameter
                ifModifiedKey = s.url;
                // Add anti-cache in url if needed
                if (s.cache === false) {
                    var ts = jQuery.now(),
                    // try replacing _= if it is there
            ret = s.url.replace(rts, "$1_=" + ts);
                    // if nothing was replaced, add timestamp to the end
                    s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
                }
            }
            // Set the correct header, if data is being sent
            if (s.data && s.hasContent && s.contentType !== false || options.contentType) {
                jqXHR.setRequestHeader("Content-Type", s.contentType);
            }
            // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
            if (s.ifModified) {
                ifModifiedKey = ifModifiedKey || s.url;
                if (jQuery.lastModified[ifModifiedKey]) {
                    jqXHR.setRequestHeader("If-Modified-Since", jQuery.lastModified[ifModifiedKey]);
                }
                if (jQuery.etag[ifModifiedKey]) {
                    jqXHR.setRequestHeader("If-None-Match", jQuery.etag[ifModifiedKey]);
                }
            }
            /*设置dataType,达到预期服务器返回的数据类型,如果没有dataType参数,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断
              默认的s.accepts=  accepts: {xml: "application/xml, text/xml",
              html: "text/html",text: "text/plain",json: "application/json, text/javascript","*": allTypes}  
              allTypes= ['*\/']+['*']  如果设置了dataType参数,即 s.dataTypes = jQuery.trim(s.dataType || "*").toLowerCase().split(/\s+/);
               比如:$(url,{dataType:"json"}) 这里第二个参数将成为 "application/json, text/javascript"+",*\/*;q=0.01"
            */
            jqXHR.setRequestHeader(
            "Accept",
            s.dataTypes[0] && s.accepts[s.dataTypes[0]] ?
                s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== "*" ? ", " + allTypes + "; q=0.01" : "") :
                s.accepts["*"]
        );
            //检查头部是否是指了参数 s.headers={} 一个额外的"{键:值}"对映射到请求一起发送                    -->我们没设置头部
            for (i in s.headers) {
                jqXHR.setRequestHeader(i, s.headers[i]);
            }
            // Allow custom headers/mimetypes and early abort
            if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || state === 2)) {
                // Abort if not done already
                jqXHR.abort();
                return false;
            }
            //$.ajax().success(callback).error(callback).complete(callback) 在这里增加callback,这里表面现在的ajax请求可以不止一个回调函数
            for (i in { success: 1, error: 1, complete: 1 }) {
                jqXHR[i](s[i]);
            }
            // Get transport
            transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);
            // If no transport, we auto-abort
            if (!transport) {
                done(-1, "No Transport");
            } else {
                jqXHR.readyState = 1;
                // Send global event
                if (fireGlobals) {
                    globalEventContext.trigger("ajaxSend", [jqXHR, s]);
                }
                // Timeout设置请求超时时间(毫秒),超时请求后,jqXHR.abort() 中止请求,简单的意思就是在指定的时间内还未响应,停止请求
                if (s.async && s.timeout > 0) {                                     
                    timeoutTimer = setTimeout(function () {      -
                                                           ->这里知道我们为什么设置timeout了吧,就是如果在timeout时间内还没请求到数据
                        jqXHR.abort("timeout");               肯定得停止了,如何停止的,得看abort.提前是我们设置了这个参数并且是异步请求
                    }, s.timeout);
                }
                try {
                    state = 1;
                    transport.send(requestHeaders, done);              
                                                                -->这个方法就能知道jQuery是如何异步跨越请求这个js文件的,见下面分析
                } catch (e) {
                    // Propagate exception as error if not done
                    if (state < 2) {                                      -->处理上面这个方法的异常,万一你传得url不存在呢。。。
                        done(-1, e);
                        // Simply rethrow otherwise
                    } else {
                        jQuery.error(e);
                    }
                }
            }
            return jqXHR;                              -->分析到这里,怎么办了?其实看出来,我们只分析了$.ajax()并没用分析后面那段链式操作,
        },                                                  还有js文件怎么请求的,请求到哪儿了?先回到上面的done方法
上面代码的-->指出了这段代码关键的运行,以及为什么我们可以直接$.ajax().done().done()异步处理任务,而且可以同时增加多个回调函数,这多得多亏$.Deferred().
好吧,重点来分析怎么transport.send(requestHeaders,done)来跨域请求我们的js文件吧...怎么jQuery一个ajax这么复杂?还不是为了迎合上千万使用者不同的使用目的。也许对你来说,
你只需要一个简单的ajax请求,我才不管他跨域了没有!这里就是jQuery的一个缺点吧,木办法啊,你们怎么多使用者,我要每个都照顾啊!好吧,来分析js怎么请求的吧
/* 绑定script分发器,通过在header中创建script标签异步载入js. -->看到这里,你会有点了解这个transports分发器在干什么了,
谁叫你要请求js文件啊,还是跨域的,我平时就请求一个.php,没想这么多~_~,
原来ajax可以请求这么多东西
*/
jQuery.ajaxTransport("script", function (s) { if (s.crossDomain) { -->我可是跨域请求哦 var script,
head = document.head || document.getElementsByTagName("head")[0] || document.documentElement; //一步步的获取head元素 return {
/*以下即是异步加载js的常用方法
*/
send: function (_, callback) { -->尼玛的send方法在这里,藏得太深了 script = document.createElement("script"); -->好吧,看到这里,你觉得是不是突然jQuery里怎么会有这么简单的代码了? script.async = "async"; if (s.scriptCharset) {
script.charset = s.scriptCharset;
} script.src = s.url; // script加载完成触发的callback
script.onload = script.onreadystatechange = function (_, isAbort) { -->js文件加载后的callback
//中止script回调请求或者不存在readyState|| load|complete状态
if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) { //处理ie下得内存泄露问题 ,onload事件触发后,销毁事件.
script.onload = script.onreadystatechange = null; if (head && script.parentNode) { ->head.removeChild(script)?你把我才加载进来的js文件删了
干嘛啊,自己想吧
head.removeChild(script); //加载过后删除script标签元素
} // 注销script变量
script = undefined; ->真把加载进来的script清的一干而尽,看来只能跨域请求js,然后执行一次callback而已,
->有点划不来吧 ~_~ // 如果没有被中止调用callback
if (!isAbort) {
callback(200, "success"); ->这个callback是神马呢?就是上面的done方法,然后这个done方法里面根据不
同的status进行不同的请求,你没忘吧!
}
}
};
//把创建的script加入head头部,但是加载完成后会被清除该script标签
head.insertBefore(script, head.firstChild);
-->把我们请求的js文件加到头部,不加到头部没办法执行里面的函数 ~_~,
执行了又把人家删了
},
/*手动中止script请求
*/
abort: function () { --> 好吧,我们没有abort
if (script) {
script.onload(0, 1);
}
}
};
}
});
这只是一个简单的跨域请求js文件,怎么这么多代码?哎,这个jQuery ajax的参数配置太多了,他会不停的if再if ,这些if造就了jQuery的调用接口这么灵活了,可以这么写,也可以那么写,满足不同
的人的口味。 分析到这里,可能你已经头很大了,木办法,它确实很难,这只是ajax的一部分。
好吧,我承认上面都是低级$.ajax方法,为了满足调用者使用更简单,作者提供了$.get() $.post(),$.getScript(),$.getJSON(),哎,一切为了减少使用者的负担啊,本来是没必要加这些代码的
还是来看看,这几个方法怎么基于$.ajax写出来的,其实很简单了,如果你真真看懂了$.ajax ~_~
/*这里遍历数组扩展$.get() $.post();其实都还是调用的$.ajax,只是type不同
* 这里$.ajax还是返回jqXHR,它与以前版本不同之处是它是超集的XMLHTTPRequest,由于deferred.promise(jqXHR);使这个jqXHR多了一些done,fail,always方法,
* 当然也可以success,fail,complete其实这些方法就是done,fail,always,详情可见$.ajax和$.Deferred对象
*/
jQuery.each(["get", "post"], function (i, method) { -->老生常谈得遍历数组,扩展$.method ,
以后我一定帮你们分析下jQuery核心库代码^_^
jQuery[method] = function (url, data, callback, type) {
//这里就是$.get("url",function(){})式的调用方法
if (jQuery.isFunction(data)) { //统一成$.get("url",data,function(){})
type = type || callback;
callback = data;
data = undefined; //把第二个参数设置成undefined,其目的也是是$.get()的接口灵活,
//从这里可以看出jQuery的调用接口灵活还是基于强大的if判断语句
}
//这里返回1.5版本之前的ajax调用方式
return jQuery.ajax({ -->搞来搞去还是$.ajax,只是帮你设置了参数了
type: method, //get or post
url: url,
data: data,
success: callback,
dataType: type
});
};
}); getScript: function (url, callback) { ->尼玛的,还是调用的get,话说这个方法可以用了动态加载js文件,也可以按需加载哦,
相当于jQuery的js加载器吧,好扯的加载器,
return jQuery.get(url, undefined, callback, "script");
},
//json文件,所有在JSON字符串表示,无论是属性或值,必须用双引号括起来,如{"key1":"value1","key2",:"value2"}保存在一个test.json文件中
//$.getJSON("test.json",function(data){$.each(data,function(key,value){})});
getJSON: function (url, data, callback) {
return jQuery.get(url, data, callback, "json");
},
jQuery deferred应用之ajax详细源码分析(二)的更多相关文章
- jQuery 2.1.4版本的源码分析
		jQuery 2.1.4版本的源码分析 jquery中获取元素的源码分析 jQuery.each({// 获取当前元素的父级元素 parent: function(elem) { var parent ... 
- Tomcat源码分析二:先看看Tomcat的整体架构
		Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ... 
- 十、Spring之BeanFactory源码分析(二)
		Spring之BeanFactory源码分析(二) 前言 在前面我们简单的分析了BeanFactory的结构,ListableBeanFactory,HierarchicalBeanFactory,A ... 
- Vue源码分析(二) : Vue实例挂载
		Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ... 
- Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题
		4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ... 
- 框架-springmvc源码分析(二)
		框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ... 
- 多线程之美8一 AbstractQueuedSynchronizer源码分析<二>
		目录 AQS的源码分析 该篇主要分析AQS的ConditionObject,是AQS的内部类,实现等待通知机制. 1.条件队列 条件队列与AQS中的同步队列有所不同,结构图如下: 两者区别: 1.链表 ... 
- jQuery Deferred对象详细源码分析(-)
		本系列文章讲介绍这个Deferred东西到底拿来干什么,从1.5版本加进来,jQuery的很多代码都重写了.直接先上源码分析了,清楚了源码分析,下节将讲具体的应用 以及应用场景. 创建对象 var d ... 
- jquery中的$.ajax()的源码分析
		针对获取到location.href的兼容代码: try { ajaxLocation = location.href; } catch( e ) { // Use the href attribut ... 
随机推荐
- oracle 导入imp 命令
			最常用的 imp name/password@IP:1521/orcl[库] file="c:\123.dmp" full=y ignore=y. 例:imp abc/ ... 
- a标签无法传递中文参数问题的解决
			a标签无法传递中文参数问题的解决. 可以通过form表单提交 隐藏域的方法解决. 前台jsp页面: <a class="vsb_buton" href="javas ... 
- 让人头疼一晚上的 select 下拉框赋值问题
			一开始做这个功能 批量修改用户组 , 当勾选若干用户组后, 点击[批量修改用户组]->ajax提交后台查询->返回下拉菜单列表内容-> 弹出对话框并赋予下拉菜单select 动态数值 ... 
- python下载各大主流视频网站电影
			You-Get 是一个命令行工具, 用来下载各大视频网站的视频, 是我目前知道的命令行下载工具中最好的一个, 之前使用过 youtube-dl, 但是 youtube-dl 吧, 下载好的视频是分段的 ... 
- docker容器磁盘
			docker容器磁盘扩容 一.配置文件里更改容器创建时的默认磁盘大小 [root@ip---- ~]# cat /etc/sysconfig/docker-storage DOCKER_STORAGE ... 
- 《Kubernetes权威指南第2版》学习(二)一个简单的例子
			1: 安装VirtualBox, 并下载CentOS-7-x86_64-DVD-1708.iso, 安装centOS7,具体过程可以百度. 2:开启centOS的SSH, 步骤如下: (1) yum ... 
- Lecture0 -- Introduction&&Linear Regression with One Variable
			Introduction What is machine learning? Tom Mitchell provides a more modern definition: "A compu ... 
- 如何在ubuntu下使用windows下的程序(eg: .exe)
			为了在ubutu下安装百度云管家,上网查了下如何在ubuntu 下安装.exe文件,其中遇到一些问题记录如下: 使用的命令: 开始时直接使用的sudo apt-get install wine 在运行 ... 
- 【Linux学习】Linux文件系统5—查看文件内容命令
			Linux文件系统5-查看文件内容命令 cat: 由第一行开始显示文件内容 more: 一页一页地显示文件内容,空格键可以继续翻页显示下一页内容 less:与more类似,但是可以往前翻页 head: ... 
- 用Go语言异常机制模拟TryCatch异常捕捉
			有的同学看到Go和TryCatch一起出现,心里可能会说,难道Go语言升级了,加入了try...catch语句.哈哈,其实Go语言从创建之初就没打算加入try...catch语句,因为创建Go的那帮大 ... 
