前后端通信

同源策略

  • 同源策略(MDN 解释):限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。
  • 源:协议、域名、端口。
  • 限制:无法获取 Cookie 、 LocalStorage 和 IndexDB ,无法操作 dom ,不能发送 Ajax 。

前后端通信方式

  • Ajax:不支持跨域。
  • WebSocket:支持跨域。
  • CORS:支持跨域。

onreadystatechange 事件

readyState:

  • 0:请求未初始化
  • 1:服务器连接已建立
  • 2:请求已接收
  • 3:请求处理中
  • 4:请求完成,响应就绪

触发顺序:

  1. xhr.onreadystatechange
  2. xhr.onloadstart
  3. xhr.upload.onloadstart
  4. xhr.upload.onprogress
  5. xhr.upload.onload
  6. xhr.upload.onloaded
  7. xhr.onprogress
  8. xhr.onload
  9. xhr.onloaded

Ajax 请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var ajax = function (param) {
// 兼容性处理
var xhr = XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP")

var type = (param.type || "get").toUpperCase()
var url = param.url
if (!url) {
return
}
var data = param.data,
dataArr = []

// 构造数组
for (var key in data) {
dataArr.push(key + "=" + data[key])
}

if (type === "GET") {
url = url + "?" + dataArr.join("&")
xhr.open(type, url)
xhr.send()
} else if (type === "POST") {
xhr.open(type, url)

// post 请求头
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")

xhr.send(dataArr.join("&"))
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200 || xhr.status == 304) {
if (param.success && param.success instanceof Function) {
var result = xhr.responseText
if (typeof result === "string") {
result = JSON.parse(result)
param.success.call(xhr, result)
}
}
}
}
}
}

update: Promise 改造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var ajax = ({ type, url, data, header }) =>
new Promise((resolve, reject) => {
// 兼容性处理
var xhr = XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP")

type = (type || "get").toUpperCase()
if (!url) return
let dataArr = []

// 构造数组
for (var key in data) {
dataArr.push(key + "=" + data[key])
}

if (type === "GET") {
url = url + "?" + dataArr.join("&")
xhr.open(type, url)
xhr.send()
} else if (type === "POST") {
xhr.open(type, url)

// post 请求头
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
for (let key in header) xhr.setRequestHeader(key, header[key])

xhr.send(dataArr.join("&"))
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200 || xhr.status == 304) {
resolve.call(undefined, xhr.responseText)
} else reject.call(undefined, xhr)
}
}
})

跨域通信的方式:

  • JSONP:只支持 GET 请求,通过 script 的异步加载实现
  • WebSocket
  • CORS:跨域时,会在请求头增加 Origin 字段
  • Hash
  • postMessage: window.postMessage() 发送