共计 3460 个字符,预计需要花费 9 分钟才能阅读完成。
ajax 及 fetch API 详解
-
XMLHttpRequest
const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://domain/serivce'); // 须要留神的是 在申请发送前建设对状态的监听 有可能申请响应十分快,状态监听还没有实现 xhr.onreadystatechange = function (){if(xhr.readyState !== 4){return;} if(xhr.status === 200){console.log(xhr.responseText) }else{console.error(`HTTP error, status=${xhr.status},errorText=${xhr.statusText}`); } } // 超时 xhr.timeout = 3000; xhr.ontimeout = () => {console.log('以后申请超时啦') } // 文件上传进度 xhr.upload.onprogress = p => {const precent = Math.round((p.loaded / p.total) * 100) + '%'; } xhr.send();
- fetch
- 默认不带 cookie
- 谬误不会 reject
- 不反对超时设置
- 须要通过 AbortController 终止 fetch
fetch('http://domain/serivce', {
method: 'GET',
credentials: 'same-origin', // omit: 默认 不带 cookie same-origin:同域携带 cookie include:即可同域携带,也可跨域携带
}).then(response => {if(response.ok){
// 申请胜利
return response.json;
}
throw new Error('http error');
}).then(json => {console.log(json)
}).catch(error => {
// 接管整体 fetch 谬误 throw new Error 谬误
console.log(error);
})
封装一个 fetch 超时
function fetchTimeout(url, init, timeout = 3000){return new Promise((resolve, reject) => {fetch(url, init).then(resolve).catch(reject);
setTimeout(reject, timeout);
})
}
// 尝试一下:封装一个通用的异步函数的超时
// function (fn, timeout){}
中断 fetch
const controller = new AbortController();
fetch('http://domain/serivce', {
method: 'GET',
credentials: 'same-origin',
siginal: controller.siginal
}).then(response => {if(response.ok){
// 申请胜利
return response.json;
}
throw new Error('http error');
}).then(json => {console.log(json)
}).catch(error => {console.log(error);
})
// 勾销
// 会中断所有 controller.siginal 的 fetch
controller.abort();
常见的浏览器申请 / 响应头 / 错误码解析
request header
method
path
cookie
referer: 判断浏览器来自哪个页面,标识拜访门路
user-angent:常常用来判断各种各样的环境,比方做投放业务
response header
access-control-allow-origin: 制订具体域名 或者 * 不做限度
content-encoding: gzip
set-cookie
status
200 get 胜利
201 post 胜利
301 永恒重定向
302 长期重定向
304 协商缓存 服务器文件未修改
400 客户端申请有语法错误,不能被服务器辨认
403 服务器受到申请,然而回绝提供服务,可能是跨域
404 申请的资源不存在
405 申请的 method 不容许
500 服务器产生不可预期的谬误
强缓存
max-age 毫秒数,接管 cookie 多少毫秒后生效
expired 代表什么时候过期,工夫扭转之后 cookie 有效性会产生偏差
协商缓存
last-modified 判断以后文件是否被批改 毛病:在服务器关上不作任何批改 last-modified 还是会扭转
eTag 把整体文件内容进行了 hash 判断文件是否有过批改 更加准确 然而更加耗费性能
问:为什么常见的 cdn 域名和业务域名不一样?
<!– www.baidu.com –>
<!– cdn.baidu-aa.com –>
- 平安问题 cookie 携带了身份信息,域名雷同的话会把不必要的用户信息传给 cdn 厂商,公司不想裸露
- cdn request header 会携带 cookie , 无畏的减少了更多的带宽占用、资源耗费
问:常见的 vue react spa 利用,都会存在 index.html 文件,也就是所谓的单页,针对 index.html 要做缓存的话,适宜做什么缓存?
如果肯定要做的话,协商缓存。
spa 利用的 html 文件非常简单,可能基本没有什么内容,编译产出的 script css 文件会变成 script link 标签插入 html 外面,而这些文件自身是有 hash 命名的,是为了避免 js css 的缓存,然而 index.html 是没有 hash 的。
js 文件更新十分频繁,如果做了强缓存,更新不能实时下发到用户端上去;如果做了协商缓存,每次打包文件都会产生扭转,就能够失常拉去更新代码。
失常的的话是 no-cache no-store
发送申请的示例,以及封装一个多浏览器兼容的申请函数
interface IOption{
url: string,
type?: 'GET' | 'POST',
data: any,
timeout?: number
}
function formatUrl(object){const dataArr = [];
for(let key in object){dataArr.push(`${key}=${encodeURIComponent(object[key])}`)
}
return dataArr.join('&');
}
export function ajax(options: IOption = {
url: '',
type: 'GET',
data: {},
timeout: 3000
}) {return new Promise((resolve, reject) => {if(!options.url){return ;}
const queystring = formatUrl(options.data);
let timer;
let xhr;
const onStateChange = () => {xhr.onreadystatechange = () => {if(xhr.readyState === 4){if(xhr.status >= 200 && xhr.status <= 300 || xhr.status === 304){resolve(xhr.responseText);
}else{reject(xhr.status);
}
}
}
}
if((window as any).XMLHttpRequest){xhr = new XMLHttpRequest();
}else{xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
if(options.type.toLowerCase() === 'GET'){xhr.open('GET', `${options.url}?${queystring}`);
xhr.send();}else if(options.type.toLowerCase() === 'POST'){xhr.open('POST', options.url);
xhr.setRequestHeader('ContentType', 'application/json')
xhr.send(options.data);
}
if(options.timeout){timer = setTimeout(() => {xhr.abort();
reject('timeout')
}, options.timeout)
}
})
}