一、问题描述
- 在使用mock.js,按照网上的说法rurl必须使用正则,否则会报404,出于好奇,专门将rurl写成String类型试了一下,果然报404,以下是我尝试的方式,发现都报404,后面看了一下源码,方式一和方式二是因为rurl与请求路径不相等导致的,但是方式三为什么也报404呢,后来才发现问题出在t这个参数,它是时间戳,所以每次请求都不一样t都不一样,尽管我把network中的Request URL复制下来,那下一次请求时这个t还是会不一样的
Mock.mock("ed/yearPlanCompany/page", "get", getYearPlanCompanyList);
Mock.mock("http://1.13.248.232:8110/ed/yearPlanCompany/page", "get", getYearPlanCompanyList);
Mock.mock("http://1.13.248.232:8110/ed/yearPlanCompany/page?order=&orderField=&page=1&limit=10&_t=1679572468049", "get", getYearPlanCompanyList);
- 为了验证我的想法,将get改为post同时请求,发现get方法报404,而post方法被成功拦截,即在network中没有post方法的请求
mounted() {
this.busOn();
baseService.post("ed/yearPlanCompany/page").then((res) => {
console.log(res);
});
},
Mock.mock("ed/yearPlanCompany/page", "get", getYearPlanCompanyList);
Mock.mock("http://1.13.248.232:8110/ed/yearPlanCompany/page", "post", getYearPlanCompanyList);
二、查找原因
于是找了一下mockjs的源码发现,mockjs在处理String类型和Regexp类型时的方式不一样
- 首先当前端正常请求接口时,会创建原生XHR对象,然后执行open方法(此时可以取到 URL,可以决定是否进行拦截),open方法里面的find()方法( 查找与请求参数匹配的数据模板)在这里起了关键作用,在find中如果rurl是string类型,则需要判断rurl与请求地址是否相等,如果rurl是regexp类型,则只需要判断rurl与请求地址是否匹配,相等或者匹配才会返回匹配的数据模板,如果未找到匹配的数据模板,则采用原生 XHR 发送请求。
open: function(method, url, async, username, password) {
var that = this
Util.extend(this.custom, {
method: method,
url: url,
async: typeof async === 'boolean' ? async : true,
username: username,
password: password,
options: {
url: url,
type: method
}
})
this.custom.timeout = function(timeout) {
if (typeof timeout === 'number') return timeout
if (typeof timeout === 'string' && !~timeout.indexOf('-')) return parseInt(timeout, 10)
if (typeof timeout === 'string' && ~timeout.indexOf('-')) {
var tmp = timeout.split('-')
var min = parseInt(tmp[0], 10)
var max = parseInt(tmp[1], 10)
return Math.round(Math.random() * (max - min)) + min
}
}(MockXMLHttpRequest._settings.timeout)
// 查找与请求参数匹配的数据模板
var item = find(this.custom.options)
function handle(event) {
// 同步属性 NativeXMLHttpRequest => MockXMLHttpRequest
for (var i = 0; i < XHR_RESPONSE_PROPERTIES.length; i++) {
try {
that[XHR_RESPONSE_PROPERTIES[i]] = xhr[XHR_RESPONSE_PROPERTIES[i]]
} catch (e) {
}
}
// 触发 MockXMLHttpRequest 上的同名事件
that.dispatchEvent(new Event(event.type /*, false, false, that*/ ))
}
// 如果未找到匹配的数据模板,则采用原生 XHR 发送请求。
if (!item) {
// 创建原生 XHR 对象,调用原生 open(),监听所有原生事件
var xhr = createNativeXMLHttpRequest()
this.custom.xhr = xhr
// 初始化所有事件,用于监听原生 XHR 对象的事件
for (var i = 0; i < XHR_EVENTS.length; i++) {
xhr.addEventListener(XHR_EVENTS[i], handle)
}
// xhr.open()
if (username) xhr.open(method, url, async, username, password)
else xhr.open(method, url, async)
// 同步属性 MockXMLHttpRequest => NativeXMLHttpRequest
for (var j = 0; j < XHR_REQUEST_PROPERTIES.length; j++) {
try {
xhr[XHR_REQUEST_PROPERTIES[j]] = that[XHR_REQUEST_PROPERTIES[j]]
} catch (e) {
}
}
return
}
// 找到了匹配的数据模板,开始拦截 XHR 请求
this.match = true
this.custom.template = item
this.readyState = MockXMLHttpRequest.OPENED
this.dispatchEvent(new Event('readystatechange' /*, false, false, this*/ ))
},
- find()方法源码
// 查找与请求参数匹配的数据模板:URL,Type
function find(options) {
for (var sUrlType in MockXMLHttpRequest.Mock._mocked) {
var item = MockXMLHttpRequest.Mock._mocked[sUrlType]
if (//这里将rurl传入match中
(!item.rurl || match(item.rurl, options.url)) &&
(!item.rtype || match(item.rtype, options.type.toLowerCase()))
) {
// console.log('[mock]', options.url, '>', item.rurl)
return item
}
}
function match(expected, actual) {
console.log({
expected, actual })
//如果rurl是string类型,则需要判断rurl与请求地址是否相等
if (Util.type(expected) === 'string') {
return expected === actual
}
//如果rurl是regexp类型,则只需要判断rurl与请求地址是否匹配
if (Util.type(expected) === 'regexp') {
return expected.test(actual)
}
}
}