原生XMLHttpRequest學習日誌

今天決定學習一下Ajax異步的XMLHttpRequest對象,平時一直使用jQuery.ajax()就萬事大吉,javascript

當本身要實現一套時才發現當中的細節事情!jQuery源碼真的博大精深優美得很;php

先從w3cschool看一下基本的使用方式,參考的jQ版本是v1.11.1html

http://www.w3school.com.cn/xml/xml_http.asp java

基本流程是先作簡單XMLHttpRequest兼容處理,提交請求,最後是回調處理結果;
node

setup1 配置ajax

開始時候在想怎樣才能寫出優美的參數傳值,看jQ源碼發現是使用jQuery.extend,並且這函數在不少地方都在應用,看來份量很重噢;json

手冊介紹是用一個或多個其餘對象來擴展一個對象,返回被擴展的對象;若是不指定target,則給jQuery命名空間自己進行擴展。跨域

jQ是先定義了基本參數對象ajaxSettings#8830行開始;而後調用ajaxSetup方法,其實這貨仍是調用了jQuery.extend去合併對象;只是判斷是不是擴展配置對象;瀏覽器

本身太賴了只作最簡參數單合併和獲取回調方法事情;服務器

function ajaxSetup(opations) {
		if (typeof opations == 'object') {
			for (key in opations) {
			    //Code....
			}
		}
		return ajaxSetting;
	}

setup2

實例化XMLHttpRequest就交由兩個方法isWindowXHR和isIEXHR,而後由JS自行判斷使用哪個;

這裏基本沒什麼特別!jQuery基本也是這麼幹的!只是它還作了不少IE6~9的瀏覽器兼容代碼(難關jQ2就放棄治療它們)

        // Create the request object
        // (This is still attached to ajaxSettings for backward compatibility)
        jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
	// Support: IE6+
	function() {

		// XHR cannot access local files, always use ActiveX for that case
		return !this.isLocal &&

			// Support: IE7-8
			// oldIE XHR does not support non-RFC2616 methods (#13240)
			// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
			// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
			// Although this check for six methods instead of eight
			// since IE also does not support "trace" and "connect"
			/^(get|post|head|put|delete|options)$/i.test( this.type ) &&

			createStandardXHR() || createActiveXHR();
	} :
	// For all other browsers, use the standard XMLHttpRequest object
	createStandardXHR;

我萬惡地幾行沒營養的代碼就行了!

        var xmlHttp = isWindowXHR() || isIEXHR();
        
	function isWindowXHR() {
		//Code....
	}

	function isIEXHR() {
		//Code....
	}

setup3 傳值請求服務器和處理回調

這裏jQ作了不少參數值的過濾、是不是跨域請求、head部分組裝,是否跨域分開了好像是兩部分處理(不知道有沒有看錯!代碼太長了)

搜源碼jQuery.ajaxTransport能夠找到;

而後也是跟XMLHttpRequest流程定義調用send處理onreadystatechange在不一樣狀態觸發事件;

        //TODO:增長其餘狀態處理
	function stateChange() {
		if (xmlHttp.readyState == 4) {
			//Code....
		}
	}
	
	return {
		'ajax' : function(opations) {
			var settings = ajaxSetup(opations);
			if (xmlHttp !== null && settings) {
				xmlHttp.onreadystatechange = stateChange;
				switch(settings['type'].toUpperCase())
				{
					case 'POST':
						//Code....
					break;

					case 'GET':
						//Code....
					break;
				}
			} else {
				alert("Your browser does not support XMLHTTP.");
			}
		}
	};

在此次學習中發現一個很好的網站

whatwg.org

後來發現這傢伙跟W3C是頗有冤緣;

詳細看這裏《哪一個HTML5?WHATWG與W3C或分道揚鑣》

http://www.cnblogs.com/xesam/archive/2012/07/23/2604254.html


完整代碼:

index.html

<DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script type="text/javascript" src="xhr.js"></script>
	</head>
	<body>
		<input type="button" id="gTime" value="獲取服務器時間" />
		<div id="serTime">00:00:00</div>
	</body>
</html>
<script type="text/javascript">
	gTime.addEventListener("click", function(){
		$.ajax({
			type: "POST",
			url: "xmlHttpRequestAction.php",
			dataType : 'json',
			async : true,
			data: "name=John&location=Boston",
			success : function(msg) {
				var obj = eval('(' + msg + ')');
				serTime.childNodes[0].nodeValue = obj.date;
				console.log(obj);
			}
		});
	}, false);
</script>

xhr.js

var $ = (function(Global){

	var xmlHttp = isWindowXHR() || isIEXHR();

	var callback = {};

	var ajaxSetting = {
		//TODO:過濾地址符號,例如結尾的"/"
		'url'   : location.href,
		'type'  : 'GET',
		//TODO:增長類型轉換判斷
		'dataType' : 'text',
		'async' : true,
		//TODO:增長支持對象類型
		'data'  : null
	};

	function isWindowXHR() {
		try {
			if (window.XMLHttpRequest) {
				return new XMLHttpRequest();
			}
		} catch (e) {}
	}

	function isIEXHR() {
		try {
			if (window.ActiveXObject) {
				return new ActiveXObject("Microsoft.XMLHTTP");
			}
		} catch (e) {}
	}

	function ajaxSetup(opations) {
		if (typeof opations == 'object') {
			for (key in opations) {
				if (typeof ajaxSetting[key] !== 'undefined') {
					ajaxSetting[key] = opations[key];
				} else {
					switch(typeof opations[key])
					{
						case 'function':
							callback[key] = opations[key];
						break;
					}
				}
			}
		}
		return ajaxSetting;
	}

	//TODO:增長其餘狀態處理
	function stateChange() {
		if (xmlHttp.readyState == 4) {
			if (xmlHttp.status == 200) {
				if (callback.success) {
					//Success
					return callback.success(xmlHttp.responseText);
				} else {
					return xmlHttp.response;
				}
			} else {
				alert("Problem retrieving XML data");
			}
		}
	}

	/* https://xhr.spec.whatwg.org/ */
	return {
		'ajax' : function(opations) {
			var settings = ajaxSetup(opations);
			if (xmlHttp !== null && settings) {
				xmlHttp.onreadystatechange = stateChange;
				switch(settings['type'].toUpperCase())
				{
					case 'POST':
						xmlHttp.open('POST', settings['url'], settings['async']);
						xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
						xmlHttp.send(ajaxSetting['data']);
					break;

					case 'GET':
						settings['url'] += ('?' + ajaxSetting['data']);
						xmlHttp.open('GET', settings['url'], settings['async']);
						xmlHttp.send(null);
					break;
				}
			} else {
				alert("Your browser does not support XMLHTTP.");
			}
		}
	};

})(window);

xmlHttpRequestAction.php

<?php
date_default_timezone_set("PRC");
echo json_encode(array('date'=>date('Y-m-d h:i:s'),'POST'=>$_POST,'GET'=>$_GET, 'content'=>'中文'));
?>
相關文章
相關標籤/搜索