前端學習之Ajax(一)

1.ajax

AJAX(Asynchronous JavaScript and XML),是在瀏覽器端進行網絡編程(發送請求、接收響應)的技術方案,它使我們可以通過JavaScript 直接獲取服務端最新的內容而不必重新加載頁面。讓 Web更能接近桌面應用的用戶體驗。

簡而言之,AJAX就是瀏覽器提供的一套 API,可以通過JavaScript 調用,從而實現通過代碼控制請求與響應。實現網絡編程。

2.XMLHttpRequest對象

// 1. 創建一個 XMLHttpRequest 類型的對象 —— 相當於打開了一個瀏覽器
var xhr = new XMLHttpRequest()
// 2. 打開與一個網址之間的連接 —— 相當於在地址欄輸入訪問地址
xhr.open('GET', './time.js')
// 3. 通過連接發送一次請求 —— 相當於回車或者點擊訪問發送請求
xhr.send(null)
// 4. 指定 xhr 狀態變化事件處理函數 —— 相當於處理網頁呈現後的操作
xhr.onreadystatechange = function () {
// 通過 xhr 的 readyState 判斷此次請求的響應是否接收完成
    if (this.readyState === 4) {
    // 通過 xhr 的 responseText 獲取到響應的響應體
    console.log(this)
    }
}

(1)在open函數中可以傳遞三個參數,(1)請求方式:getpost(2)URL地址(3)truefalsetrue表示異步,false表示同步
(2)readystatechange事件,是對xhr對象狀態變化的響應,在這個過程中會響應多次。

readyState 狀態描述 說明
0 UNSENT 代理(XHR)被創建,但尚未調用 open() 方法。
1 OPENED open() 方法已經被調用,建立了連接
2 HEADERS_RECEIVED send() 方法已經被調用,並且已經可以獲取狀態行和響應頭
3 LOADING 響應體下載中, responseText 屬性可能已經包含部分數據。
4 DONE 響應體下載完成,可以直接使用 responseText

時間軸

3.具體用法

3.1get請求

var xhr = new XMLHttpRequest()
// GET 請求傳遞參數通常使用的是問號傳參
// 這裏可以在請求地址後面加上參數,從而傳遞數據到服務端
xhr.open('GET', './delete.js?id=1')
// 一般在 GET 請求時無需設置響應體,可以傳 null 或者乾脆不傳
xhr.send(null)
xhr.onreadystatechange = function () {
    if (this.readyState === 4) {
    console.log(this.responseText)
    }
}
// 一般情況下 URL 傳遞的都是參數性質的數據,而 POST 一般都是業務數據

3.2post請求

POST 請求過程中,都是採用請求體承載需要提交的數據。

var xhr = new XMLHttpRequest()
// open 方法的第一個參數的作用就是設置請求的 method
xhr.open('POST', './add.js')
// 設置請求頭中的 Content‐Type 爲 application/x‐www‐form‐urlencoded
// 標識此次請求的請求體格式爲 urlencoded 以便於服務端接收數據
xhr.setRequestHeader('Content‐Type', 'application/x‐www‐form‐urlencoded')
// 需要提交到服務端的數據可以通過 send 方法的參數傳遞
// 格式:key1=value1&key2=value2
xhr.send('key1=value1&key2=value2')
xhr.onreadystatechange = function () {
    if (this.readyState === 4) {
    console.log(this.responseText)
    }
}

3.3兼容模式

在一些老版本的瀏覽器中,對XMLHttpRequest並不是兼容的。這時我們可以通過其他的方式來進行。

var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')

4.ajax的封裝

4.1原生ajax封裝

/**
發送一個 AJAX 請求
@param {String} method 請求方法
@param {String} url 請求地址
@param {Object} params 請求參數
@param {Function} done 請求完成過後需要做的事情(委託/回調)
*/
function ajax (method, url, params, done) {
    // 統一轉換爲大寫便於後續判斷
    method = method.toUpperCase()
    // 對象形式的參數轉換爲 urlencoded 格式
    var pairs = []
    for (var key in params) {
      pairs.push(key + '=' + params[key])
    }
    var querystring = pairs.join('&')
    var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new
    ActiveXObject('Microsoft.XMLHTTP')
    xhr.addEventListener('readystatechange', function () {
        if (this.readyState !== 4) return
          // 嘗試通過 JSON 格式解析響應體
        try {
          done(JSON.parse(this.responseText))
        } catch (e) {
          done(this.responseText)
        }
    })
    // 如果是 GET 請求就設置 URL 地址 問號參數
    if (method === 'GET') {
      url += '?' + querystring
    }
    xhr.open(method, url)
    // 如果是 POST 請求就設置請求體
    var data = null
    if (method === 'POST') {
        xhr.setRequestHeader('Content‐Type', 'application/x‐www‐form‐urlencoded')
        data = querystring
    }
    xhr.send(data)
}

ajax('get', './get.js', { id: 123 }, function (data) {
  console.log(data)
})
ajax('post', './post.js', { foo: 'posted data' }, function (data) {
  console.log(data)
})

4.2jQuery中的ajax

$.ajax({
	url: './get.js',
	type: 'get',
	dataType: 'json',
	data: { id: 1 },
	beforeSend: function (xhr) {
	console.log('before send')
	},
    success: function (data) {
        console.log(data)
    },
    error: function (err) {
        console.log(err)
    },
    complete: function () {
        console.log('request completed')
    }
})

常用選項參數介紹:
url:請求地址
type:請求方法,默認爲 get
dataType:服務端響應數據類型
contentType:請求體內容類型,默認 application/x-www-form-urlencoded
data:需要傳遞到服務端的數據,如果 GET 則通過 URL 傳遞,如果 POST 則通過請求體傳遞
timeout:請求超時時間
beforeSend:請求發起之前觸發
success:請求成功之後觸發(響應狀態碼 200)
error:請求失敗觸發
complete:請求完成觸發(不管成功與否)

5.跨域問題

5.1跨域

同源策略是瀏覽器的一種安全策略,所謂同源是指域名,協議,端口完全相同,只有同源的地址纔可以相互通過AJAX 的方式請求。
同源或者不同源說的是兩個地址之間的關係,不同源地址之間請求我們稱之爲跨域請求
例如:http://www.example.com/detail.html

對比地址 是否同源 原因
http://api.example.com/detail.html 不同源 域名不同
https://www.example.com/detail.html 不同源 協議不同
http://www.example.com:8080/detail.html 不同源 端口不同
https://api.example.com/detail.html 不同源 協議、域名不同
http://www.example.com/other.html 同源 只是目錄不同

5.2解決方案

5.2.1. JSONP

JSON with Padding,是一種藉助於 script 標籤發送跨域請求的技巧。

其原理就是在客戶端藉助 script 標籤請求服務端的一個動態網頁,服務端的這個動態網頁返回一段帶有函數調用的 JavaScript 全局函數調用的腳本,將原本需要返回給客戶端的數據傳遞進去。

以後絕大多數情況都是採用 JSONP 的手段完成不同源地址之間的跨域請求

客戶端 http://www.zce.me/users-list.html

<script src="http://api.zce.me/users.js?callback=foo"></script>

服務端 http://api.zce.me/users.php?callback=foo 返回的結果

foo(['我', '是', '你', '原', '本', '需', '要', '的', '數', '據'])

總結一下:由於 XMLHttpRequest 無法發送不同源地址之間的跨域請求,所以我們必須要另尋他法,script 這種方案就是我們最終選擇的方式,我們把這種方式稱之爲 JSONP。

1.JSONP 需要服務端配合,服務端按照客戶端的要求返回一段 JavaScript 調用客戶端的函數
2.只能發送 GET 請求
注意:JSONP 用的是 script 標籤,更 AJAX 提供的 XMLHttpRequest 沒有任何關係!!!

5.2.2. CORS

Cross Origin Resource Share,跨域資源共享

// 允許遠端訪問
header('Access‐Control‐Allow‐Origin: *');

這種方案無需客戶端作出任何變化(客戶端不用改代碼),只是在被請求的服務端響應的時候添加一個 Access-Control-Allow-Origin的響應頭,表示這個資源是否允許指定域請求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章