浏览器请求

164 阅读3分钟

浏览器请求的三种方式

原生XMLHTTPReques

const http =new XMLHTTPRequest()
  http.open('Get''http://test/serivce')
  http.onreadystatechange=function(){
  if(http.readyState!==4)retrun
   if(http.status==200){
    //获取请求成功后的值
    console.log(http.responseText)
   }else{
     console.log('请求出错')
   }
  }
  //超时处理
  //设置超时时间
  http.timeout=30000  ///30秒
  http.ontimeout=function(){
   //超时后的处理函数
  }
  http.send()

fetch请求

//创建请求取消控制对象
const controller =  new AbortController() 
fetch(url,{
method:'请求的方式',
credentials:"same-origin"//表示的是同源的请求带cookie
signal:controller.signal //表示的是为请求关联取消控制对象
}).then(response=>{
  //请求的成功后失败都在then中进行体现  通过response.ok来判请求是否成功
  if(response.ok){
  //请求成功
  retrun response.json()
  }
  //失败则抛出异常
  throw new Error('请求异常')

}).then(json=>{
}).catch(res=>{
//这里的异常来自与网络异常,fetch执行异常 代码异常 以及throw抛出的异常
})
//请求取消
controller.abort()

fetch中默认是不支持超时处理的,但是因为fetch内部是通过promise去实现的,因此我们可以用promise规范中的 resolve 和reject的状态一旦成为fulfilled或者rejected的状态后就不能改变的特性实现超时

//封装fetch
function myFetch(url,option,timeout){
new promise((resolve,reject)=>{
 //将resolve传入  用于promise中then调用获取fetch请求回来的值
  fetch(url,option).then(resolve).catch(reject)
  //超时后进行promise状态的改变
  setTimeout(reject,timeout)
})
}


请求头

referer://请求来自于那个页面
user-ageent//识别用户的操作系统标识

相应头

access-control-allpw-origin://跨域
content-encoding//实体头用于压缩媒体类型。
set-cookie//设置cookie

状态码

200// get请求成功
201// post 请求成功
301//永久重定向
302//临时重定向
304//协商缓存  服务器文件未被修改
400	客户端请求有语法错误,不能被服务器识别
403	服务器受到请求,但是拒绝提供服务,可能是跨域
404	请求的资源不存在
405 请求的method不允许
500	服务器发生不可预期的错误

补充

cdn域名和业务域名

所谓的cdn域名可以理解成是资源域名 也就是我们项目中需要获取的资源,单单的职能就是资源的获取比如cdn图片 cdnjs等 所谓的业务域名 可以理解成就是我们数据请求的域名,这些域名一般用户我们业务中的数据请求,身份验证等。

两者之间的区别:

  1. 安全问题,业务域名中一般都包含用户的新cookie等信息,cdn 不会 2.cdn中只做资源的获取 相对来说带宽的消耗小 业务域名获取数据的时候 header中会带有各个参数消耗的带宽大

3.并发请求数。因为同源的限制如果资源域名和业务域名相同的时候,会造成在请求资源的时候阻塞数据的请求,

ajax的封装

//定义请求的接口
interface options {
    url: string,
    data?: any,
    param?: any,
    type: string,
    timeout: number
}
//参数处理
function stringQuery(data) {
    let stringQueryData = []
    for (let key in data) {
        stringQueryData.push(`${key}=${data[key]}`)
    }

    return stringQueryData.join('&')

}
export default function myAjax(option: options) {
    let xhr, timer;
    //返回一个异步的方法
    return new Promise((resolve, reject) => {
        //判断当前浏览器是否支持xmlhttprequest 属性
        if ((window as any).XMLHttpRequest) {
            xhr = new XMLHttpRequest()
        } else {
            xhr = new ActiveXObject('Microsoft.XMLHTTP')
        }
        //请求类型的判断
        if (option.type.toLocaleUpperCase() === 'GET') {
            //第三个参数表示的是  是否异步执行,true表示异步,false 表示同步
            xhr.open('get', `${option.url}?${stringQuery(option.param)}`, true)
            xhr.send();

        } else if (option.type.toLocaleUpperCase() === 'POST') {
            xhr.setRequestHeader('ContentType', 'application/x-www-form-urlencoded');
            xhr.open('get', option.url, true)
            xhr.send(option.data);
        }
        //请求处理
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                //取消定时器
                clearTimeout(timer)

                if (xhr.stats >= 200 && xhr.status < 300 || xhr.status === 304) {
                    resolve(xhr.responseText);
                } else {
                    reject('请求出错')
                }
            }


        }
        //超时设置
        // xhr.timeout=option.timeout||1000
        // xhr.ontimeout=function(){
        //     reject('请求超时')
        //     //取消请求
        // }
        if (option.timeout) {
            timer = setTimeout(() => {
                //取消请求
                xhr.abort()
                reject('请求超时')

            }, option.timeout)
        }

    })

}