如何发请求?
- 用 form 可以发请求(get 或 post),但是会刷新页面或新开页面
- 用 a 可以发 get 请求,但是也会刷新页面或新开页面
- 用 img 可以发 get 请求,但是只能以图片的形式展示
- 用 link 可以发 get 请求(link 必须放在 head中),但是只能以 CSS、favicon 的形式展示
- 用 script 可以发 get 请求(script 必须放在 head 或 body 中),但是只能以脚本的形式运行
那么有没有什么方式可以实现
get、post、put、delete 都可以发请求
想以什么形式展示就以什么形式展示
微软的突破
IE 5 率先在 JS 中引入 ActiveX 对象(API),使得 JS 可以直接发起 HTTP 请求。
随后 Mozilla、 Safari、 Opera 也跟进(抄袭)了,取名 XMLHttpRequest,并被纳入 W3C 规范
XMLHttpRequest 就是一个 window 下的全局对象
AJAX(Asynchronous JavaScript and XML)
Jesse James Garrett 将如下技术取名叫做 AJAX:异步的 JavaScript 和 XML
- 使用 XMLHttpRequest 发请求
- 服务器返回 XML 格式的字符串
- JS 解析 XML,并更新局部页面
注意:现在,服务器返回的都是 JSON 格式的数据,XML 格式已经过时了,但是 AJAX 这个名字已经成了一个通用名词,字面含义已经消失了。
使用 JSON 解析响应的第四部分(response.write)
JSON 的数据类型:
注意:
- JSON 是一门新的语言(抄袭了 JS)
- JS 的数据类型仅剩 symbol、undefined、function 没抄
- JSON 的字符串首尾必须是 "
以下是 JS 和 JSON 的几个例子的对比:
JS | JSON |
---|---|
undefined |
没有 |
null |
null |
['a' , 'b'] |
["a" , "b"] |
function fn(){} |
没有 |
{name: 'awsl'} |
{name: "awsl"} |
'awsl' |
"awsl" |
var a = {} a.self = a
|
搞不定(没有变量) |
{__proto__} |
没有原型链 |
如何使用 XMLHttpRequest
客户端(浏览器)代码:
let request = new XMLHttpRequest() // 声明一个 XMLHttpRequest 对象
request.open('get', '/xxx') // 初始化一个请求,配置 request
request.send() // 发送请求
request.onreadystatechange = () => {
if (request.readyState === 4) { // 请求完成时,状态值为 4
console.log('请求响应都完毕了')
console.log(request.status)
if (request.status >= 200 && request.status < 300) {
console.log('说明请求成功')
console.log(typeof request.responseText)
console.log(request.responseText)
let string = request.responseText // 把符合 JSON 语法的字符串转换成 JS 对应的值
let object = window.JSON.parse(string) // JSON.parse 是浏览器提供的
console.log(typeof object)
console.log(object)
console.log('object.note')
console.log(object.note)
} else if (request.status >= 400) {
console.log('说明请求失败')
}
}
}
服务器端代码:
} else if (path === '/xxx') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/json;charset=utf-8')
response.setHeader('Access-Control-Allow-Origin', 'http://frank.com:8001') // 同源策略
response.write(` // JSON
{
"note":{
"to": "AAA",
"from": "BBB",
"heading": "打招呼",
"content": "hello"
}
}
`)
response.end()
XMLHttpRequest.readyState 中请求的五种状态:
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT(未打开) | 代理被创建,但尚未调用 open() 方法 |
1 | OPENED(未发送) | open() 方法已经被调用,send()方法还没有调用 |
2 | HEADERS_RECEIVED(已获取响应头) | send() 方法已经被调用,并且头部和状态已经可获得 |
3 | LOADING(正在下载响应体) | 响应体下载中; responseText 属性已经获取了部分数据 |
4 | DONE(请求完成) | 下载操作已完成(整个请求过程已经完毕) |
同源策略
“同源”指的是“三个相同”
- 协议相同
- 域名相同
- 端口相同
只有 协议+域名+端口 完全相同才允许发 AJAX 请求
如果非同源,共有三种行为受到限制
(1) 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
(2) 无法接触非同源网页的 DOM
(3) 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)
CORS(Cross-origin resource sharing) 跨域
CORS 的全称是“跨域资源共享”,它允许浏览器向跨域的服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。
突破同源策略 === 跨域
在 response.setHeader 中设置 Access-Control-Allow-Origin,它的值要么是请求时 Origin 字段的值,要么是一个 *,表示接受任意域名的请求。
如:response.setHeader('Access-Control-Allow-Origin', 'http://frank.com:8001')
与 JSONP 的比较
CORS 与 JSONP 的使用目的相同,但是比 JSONP 更强大。JSONP 只支持GET请求,CORS 支持所有类型的 HTTP 请求。JSONP 的优势在于支持老式浏览器,以及可以向不支持 CORS 的网站请求数据。
问:为什么form表单提交没有跨域问题,但ajax提交有跨域问题?
答: 原页面用 form 提交到另一个域名之后,原页面的脚本无法获取新页面中的内容(form 会使原页面刷新),因此浏览器认为这是安全的。
而 AJAX 是可以读取响应内容的,因此浏览器不能允许你这样做。其实请求已经发送出去了,你只是拿不到响应而已。
浏览器采取这个策略的本质是:一个域名的 JS ,在未经允许的情况下,不得读取另一个域名的内容,但浏览器并不阻止你向另一个域名发送请求。
原回答:https://www.zhihu.com/question/31592553/answer/190789780
总结
- AJAX 就是用 JS 发请求
- 对于 http 来说,响应的第四部分始终为 string,可以用 JSON 语法表示一个对象,也可以用 JSON 语法表示一个数组,还可以用 XML 语法,还可以用 HTML 语法,还可以用 CSS 语法,还可以用 JS 语法,还可以用我自创的语法
- JS 是一门语言,JSON 是另一门语言,JSON 这门语言抄袭了 JS这门语言
- 请使用原生JS来发送AJAX请求
let request = new XMLHttpRequest()
request.open('get', '/xxx') // 配置request
request.send()
request.onreadystatechange = ()=>{
if(request.readyState === 4){
if(request.status >= 200 && request.status < 300){
console.log('说明请求成功')
}else if(request.status >= 400){
console.log('说明请求失败')
}
}
}
网友评论