Mockjs原理簡析
阿新 • • 發佈:2019-02-08
前言
有一個前後端分離的專案用到過Mockjs,後端提供了資料格式,前端通過模擬介面的返回資料,進行頁面的渲染,有一段時間,百思不得其解,這個外掛是怎麼把ajax請求給攔下來的,網上搜索了一番,資料甚少,未果。
後來有一天,不知道怎麼的突然想到,如果把ajax方法請求改寫了,在傳送請求之前提供一個回撥是不是能實現這個功能?
思路
- 準備環境
- 從最方便的jquery入手,打算改寫
$.ajax
- 從最方便的jquery入手,打算改寫
- 需要解決的問題主要有
$.ajax
即將被改寫,所以要自己實現一個傳送請求的xhr方法(又懶得寫封裝的ajax方法,於是把$.ajax
快取起來,以待後用)- 如何去匹配將被攔截的請求地址
- 攔截了請求之後,如何把預先準備好的資料當做請求成功後的資料
程式碼實現
let Mock = { // 儲存匹配規則 rules: new Map(), // 快取ajax方法 ajax: $.ajax, mock(url, data) { this.rules.set(url, data) } } // 改寫ajax方法 $.ajax = function(options) { Mock.ajax({ url: options.url, beforeSend(XHR) { let data = Mock.rules.get(options.url) // 找到規則攔截請求,並執行回撥(return false時會攔截請求)
- 功能檢測
- 以上程式碼可直接拷貝至控制欄執行,我們可以看到只發送了b請求,a請求被攔截了下來,同時我們也能拿到所預期的資料
- 至於Mockjs隨機資料的功能,我們暫不考慮
總結
之後我也粗略看了下Mockjs原始碼,它也是改寫了jquery和zepto的
$.ajax
方法所實現,這就意味著如果是自己用原生js封裝的ajax方法,是不能攔截的
如下,是一個原生js的ajax方法,有興趣可以自己去檢測一下:var Ajax={ get: function(url, fn) { var xhr = new XMLHttpRequest(); // XMLHttpRequest物件用於在後臺與伺服器交換資料 xhr.open('GET', url, true); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) { // readyState == 4說明請求已完成 fn.call(this, xhr.responseText); //從伺服器獲得資料 } }; xhr.send(); }, post: function (url, data, fn) { // datat應為'a=a1&b=b1'這種字串格式,在jq裡如果data為物件會自動將物件轉成這種字串格式 var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // 新增http頭,傳送資訊至伺服器時內容編碼型別 xhr.onreadystatechange = function() { if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) { // 304未修改 fn.call(this, xhr.responseText); } }; xhr.send(data); } }
- 很多公司源於方便已經提供了自己專門的mock服務平臺,以供前端開發者更快捷的模擬資料,搭建教程我會在另一篇文章中講述