实现思路
- 基于promise封装一个ajax请求
- 添加拦截和响应功能
- 添加中断请求功能
实现
搭建主体函数
// 请求发生器
function dispatchResquest (config) {}
function req(config){
// 先定义promise的成功与失败的回调
let chain = [dispatchRequest, undefined]
// 如果有请求和响应拦截,把拦截器分别加在请求生成器的前后
if(config.interceptor){
chain.unshift(config.interceptor.fulfilled, config.interceptor.rejected)
}
if(config.adaptor){
chain.push(config.adaptor.fulfilled, config.adaptor.rejected)
}
let promise = Promise.resolve(config)
// promise会先后调用拦截器,生成器,响应器的函数
while(chain.length){
promise = promise.then(chain.shift(), chain.shift())
}
}
请求发生器主体
function dispatchRequest(config){
const promise = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open(config.method.toUpperCase(), config.url, true)
xhr.send()
xhr.timeout = config.timeout
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status === 200) {
// 这里加一个定时器,方便后面中止请求的操作
setTimeout(() => resolve(xhr.responseText), 5000)
} else{
reject('request error')
}
}
}
})
return promise.then(res => res, reason => reason)
}
添加中止操作
这里的中止操作,我们用了一个发布订阅
let call = null
const mitt = {
cache: {},
on(name, func){
this.cache[name] = func
},
emit(name, data){
this.cache[name] && this.cache[name](data)
}
}
function dispatchRequest(config){
const promise = new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.open(config.method.toUpperCase(), config.url, true)
xhr.send()
xhr.timeout = config.timeout
// 取出函数
if(config.cancel){
mitt.emit('abort', function onCacel(){
xhr.abort()
xhr = null
reject('[abort] request is cancel')
})
}
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status === 200) {
// 这里加一个定时器,方便后面中止请求的操作
setTimeout(() => resolve(xhr && xhr.responseText), 5000)
} else{
reject('request error')
}
}
}
})
return promise.then(res => res, reason => reason)
}
function req(config){
// 先定义promise的成功与失败的回调
let chain = [dispatchRequest, undefined]
// 如果有请求和响应拦截,把拦截器分别加在请求生成器的前后
if(config.intercepter){
chain.unshift(config.intercepter.fulfilled, config.intercepter.rejected)
}
if(config.adaptor){
chain.push(config.adaptor.fulfilled, config.adaptor.rejected)
}
if(config.cancel){
// 存入函数
mitt.on('abort',function(cancelfunc){
config.cancel(cancelfunc)
})
}
let promise = Promise.resolve(config)
// promise会先后调用拦截器,生成器,响应器的函数
while(chain.length){
promise = promise.then(chain.shift(), chain.shift())
}
}
最后调用一下函数
本地试验一下
req({
url: 'http://127.0.0.1:5500/1.json',
method: 'GET',
interceptor: {
fulfilled: e => {
console.log('拦截', e)
return e
}
},
adaptor: {
fulfilled: e => {
console.log('响应', e)
return e
}
},
cancel(onCancel){
call = onCancel
}
})
setTimeout(() => call && call(), 2000)
没问题