网络请求 跨域处理方式
https://mp.weixin.qq.com/s/zSB7X2ka6GtxtupUtal7ig
AJAX 请求
1 | var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); |
函数
open
用于初始化一个请求
1 | xhr.open(method, url, async) |
- method:请求方法,get/post
- url:请求的 url
- async:是否为异步请求。true/false
send
用于发送 HTTP 请求
1 | xhr.send(param) |
- param:请求参数可以是
string
、Blob
等类型
abort
如果该请求已被发出,abort()
方法将终止该请求。当一个请求被终止,它的 readyState
属性将被置为 0( UNSENT )
。
1 | xhr.abort() |
setRequestHeader
用于设置 HTTP 请求头,此方法必须在 open()
方法和 send()
之间调用
1 | xhr.setRequestHeader(header, value) |
getResponseHeader
用于获取 HTTP 返回头,如果在返回头中有多个一样的名称,那么 返回值就会用逗号和空格将 值分隔的字符串。
1 | var header = xhr.getResponseHeader(name) |
属性
readyState
用来标识当前 XMLHttpRequest 对象所处的状态,XMLHttpRequest 对象总是位于下列状态中的一个:
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT | 代理被创建,但尚未调用 open()方法 |
1 | OPENED | open 方法已经被调用 |
2 | HEADERS_RECEIVED | send()方法已经被调用,并且头部和状态已经可获得 |
3 | LOADING | 下载中,responseText 属性已经包含部分数 |
4 | DONE | 下载操作已完成 |
status
表示 http 请求的状态,初始值为 0。如果服务器没有现实指定状态码,那么 status 将被设置为默认值,即 200。
responseType
表示响应的数据类型,并允许我们手动设置,如果结果为空,默认为 text 类型
|值|描述|
|-|-|
|””|将 responseType 设置空字符串与设置为 text 相同,是默认类型|
|”arraybuffer”|response 是一个包含二进制数据的 JavaScriptArrayBuffer|
|”blob”|response 是一个包含二进制数据的 Blob 对象|
|”document”|responses 是一个 HTML Document 或者 XML XMLDocument,取决于接收到数据的 MIME 类型|
|”json”|response 是一个 JavaScript 对象,这个对象时通过将接收到的数据类型为 JSON 解析|
|”text”|response 是包含在 DOMString 对象中的文本|
response
返回响应的正文,返回的类型由上面的 responseType 决定
withCredentials
ajax 请求默认会携带同源请求的 cookie,而跨域请求则不会携带 cookie,设置 xhr 的 withCredentials 的属性为 true 将允许携带跨域 cookie
事件回调
onreadystatechange
1 | xhr.onreadystatechange = callback |
当 readyState 属性发生变化时,callback 会被触发
onloadstart
1 |
|
在 ajax 请求发送之前(readyState==1 后,readyState==2 前),callback 会被触发
onprogress
1 | xhr.onprogress = function(event){ |
回调函数可以获取资源总大小 total,已经加装的资源大小 loaded,用着两个值可以计算加载进度。
onload
1 | xhr.onload = callback |
当一个资源及其依赖已完成加载时,将触发 callback,通常我们会在 onload 事件中处理返回值。 ##异常处理
onerror
1 | xhr.onerror = callback |
ajax 资源加载失败触发 callback
ontimeout
1 | xhr.ontimeout = callback |
当进度由于预定时间到期而终止时,会触发 callback,超时时间可使用 timeout 属性进行设置。
JQuery 对 Ajax 的封装
1 | $.ajax({ |
- url:请地址和接口
- type:请求类型。String。”POST”/“GET”,默认为”GET”
- timeout:Number 设置请求超时时间(毫秒),此设置将覆盖全局设置。
- success:Function,请求成功的回调函数
- error:Function,请求失败的回调函数
- jsonp:String,jsonp:’callback’
- jsonpCallback: String,函数名”onJsonPLoad”,
dataType:
- ‘xml’:返回 XML 文档,可用 JQuery 处理
- ‘html’:返回纯文本 HTML 信息,包含的 script 标签会在插入 dom 时执行
- ‘script’:返回纯文本 JavaScript 代码。不会自动缓存结果。除非设置了’cache’参数。注意:在远程请求时(不同域下),所有 POST 请求都将转为 GET 请求,(因为将使用 DOM 的 script 标签来加载)
- ‘json’:返回 JSON 数据
- ‘jsonp’:JSONP 格式,使用 JSONP 形式调用函数时如”myurl?callback=?”,jQuery 将自动替换?为正确的函数名,以执行回调函数。
- ‘text’:返回纯文字字符串
data:类型 String 使用 JSON.stringify()转码
- complete:Function,请求完成以后回调函数,请求成功或失败之后均会调用
- async:Boolean,默认为 true,异步请求,如需发送同步请求,设为 false
- contentType:String,默认’application/x-www-form-urlencoded’。发送信息至服务器时内容编码的类型。
一般键值对的形式,默认的编码方法可以处理,如 data:{a:1, b:2, c:3}
但是 json 对象存在对象嵌套数组,数组包含对象,上面的编码方式就无法处理,需要将参数利用 JSON.stringify()处理,data:JSON.stringify({a:1, [{b:2, c:3}]})
Fetch
1 | const options = { |
mode:是否跨域
- cors:允许发送跨域请求,服务器需要设置 cors 响应头
1
2
3res.header("Access-Control-Allow-Origin", "http://localhost:8888");
//或
res.header("Access-Control-Allow-Origin", "*");- no-cors:常用于在跨域不带 CORS 场景下, 此时请求发出并且会有响应,但是此时 type 为“opaque”, status 为 0 ,js 获取不到返回数据。
- same-origin:在同域下请求
- cors-with-forced-preflight:在请求前进行 preflight 检查
credentials:请求是否需要携带 cookie
- omit:不携带认证凭证 Cookie
- same-origin:在同源站点下包含凭证
- include:对所有网址包含认证凭证
- 跨域请求,不携带 cookie
- 客户端
1 | const options = { |
- node 服务器端配置
响应头设置
1 | //处理请求跨域 |
- 客户端请求允许携带 cookie
- 客户端
1 | const options = { |
- 服务器
1 | //处理请求跨域 |
获取请求的 cookie
1 | req.headers.cookie |
Fetch
执行完毕后,不能直接在 response
中获取到返回值必须调用 text()、json()、blob()、formData()
函数才能获取返回值。每次调用text()、json()
等函数后会将 bodyUsed 变量变为 true,用来标识返回值已经读取过了,下一次再读取直接抛出 TypeError(‘Already read’)。
fetch 是一个非常底层的 API,它的问题:
- 不能直接传递 JavaScript 对象作为参数
- 需要自己判断返回值类型,并执行响应获取返回值的方法
- 获取返回值方法只能调用一次,不能调用多次
- 无法正常捕获异常
- 老版浏览器默认不会携带 cookie
- 不支持 jsonp
对 fetch 的封装
请求参数的处理
1 | function stringify(url, data) { |
异常处理
1 | .then(response => { |
返回值处理
1 | .then(response => { |