乐趣区

关于javascript:浏览器相关-浏览器请求

ajax 及 fetch API 详解

  1. 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();
  2. 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 –>

  1. 平安问题 cookie 携带了身份信息,域名雷同的话会把不必要的用户信息传给 cdn 厂商,公司不想裸露
  2. 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)
        }
    })
}
退出移动版