1.什么是ajax?
AJAX:异步(A)的 JavaScript 和 XML
为什么要引入AJAX?
回答这个问题之前,我们先看下请求是怎么发的?
用 form 可以发请求,但是会刷新页面或新开页面
用 a 可以发 get 请求,但是也会刷新页面或新开页面
用 img 可以发 get 请求,但是只能以图片的形式展示
用 link 可以发 get 请求,但是只能以 CSS、favicon 的形式展示
用 script 可以发 get 请求,但是只能以脚本的形式运行
所以,考虑到以上弊端,我们想到,有没有什么方式可以实现?
get、post、put、delete 请求都行
想以什么形式展示就以什么形式展示
为此我们引入了ajax,实际上就是为了改善,JSONP不能发送get请求之外的请求。
2.具体是使用方法如下
1.使用 XMLHttpRequest 发请求
2.服务器返回 XML 格式的字符串
3.JS 解析 XML,并更新局部页面
代码如下:
myButton.addEventListener('click', (e)=>{
let request = new XMLHttpRequest()
request.open('get', '/xxx') // 配置request
request.send()
request.onreadystatechange = ()=>{
if(request.readyState === 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')
//这里是JSON的写法,具体语法下面会具体分析
response.write(`
{
"note":{
"to": "小谷",
"from": "方方",
"heading": "打招呼",
"content": "hi"
}
}
`)
response.end()
3.JSON
1.JSON是ajax中XML的上位替代,JSON是一种仿javasricpt的新语法,JSON用“”来表示字符串
2.JSON没有undefined和function
3.,没有变量,没有原型链,搞不定
var a = {}
a.self = a
{__proto__}
4.写个例子
{
"note":{
"to":"name",
"from":"who"
}
}
4.同源策略
只有 协议+端口+域名 一模一样才允许发 AJAX 请求
一模一样一模一样一模一样一模一样一模一样一模一样一模一样一模一样
- http://baidu.com 可以向 http://www.baidu.com 发 AJAX 请求吗 no
- http://baidu.com:80 可以向 http://baidu.com:81 发 AJAX 请求吗 no
浏览器必须保证
只有 协议+端口+域名 一模一样才允许发 AJAX 请求
为什么???
因为页面如果是用form表单提交到另一个域名,原页面的简本无法获取新的页面中的内容。浏览器是安全的。
但是浏览器可以读取响应的内容的(request.responseText)的,因此浏览器是不允许你这样做的。
也就是说,你可以用ajax读取页面上的信息,比如(支付宝余额,好友信息),这是没有隐私可言的,所以浏览器是不允许的。
不过如果你用Ajax向不是同源的网页发送请求,其实请求已经发出去了,你只是拿不到而已。
怎么解决这个问题?
突破同源策略就行了
使用CORS 可以告诉浏览器,我俩一家的,别阻止他
突破同源策略 === 跨域
Cross-Origin Resource Sharing
C O源 R S
CORS 跨域
使用方法如下
response.setHeader('Access-Control-Allow-Origin','http://www.baidu.com//可以跨到这里去')
总结
AJAX 的所有功能
客户端的JS发起请求(浏览器上的)
服务端的JS发送响应(Node.js上的)
JS 可以设置任意请求 header 吗?
第一部分 request.open('get', '/xxx')
第二部分 request.setRequestHeader('content-type','x-www-form-urlencoded')
第四部分 request.send('a=1&b=2')
JS 可以获取任意响应 header 吗?
第一部分 request.status / request.statusText
第二部分 request.getResponseHeader() / request.getAllResponseHeaders()
第四部分 request.responseText
tips:一个问题
浏览器是一开始就知道状态码是200还是404,还是接受完请求体之后才响应200,404的
解:一开始就知道
这个问题,要从输入网址到最终响应的这个问题答起。(这个面试题很经典)
说到响应的时候,你只要说响应的时候会会先响应200还是404
但是在开发中,我们要获得响应内容,所以要先等响应结束(request.readystate === 4)
不然没法获得的
5.手写一个ajax(就是把上面的东西封装起来)
优化之后的代码如下
window.jQuery = function(nodeOrSelector){
let nodes = {}
nodes.addClass = function(){}
nodes.html = function(){}
return nodes
}
window.$ = window.jQuery
window.Promise = function(fn){
// ...
return {
then: function(){}
}
}
window.jQuery.ajax = function({url, method, body, headers}){
return new Promise(function(resolve, reject){
let request = new XMLHttpRequest()
request.open(method, url) // 配置request
for(let key in headers) {
let value = headers[key]
request.setRequestHeader(key, value)
}
request.onreadystatechange = ()=>{
if(request.readyState === 4){
if(request.status >= 200 && request.status < 300){
resolve.call(undefined, request.responseText)
}else if(request.status >= 400){
reject.call(undefined, request)
}
}
}
request.send(body)
})
}
myButton.addEventListener('click', (e)=>{
let promise = window.jQuery.ajax({
url: '/xxx',
method: 'get',
headers: {
'content-type':'application/x-www-form-urlencoded',
'frank': '18'
}
})
promise.then(
(text)=>{console.log(text)},
(request)=>{console.log(request)}
)
})
这里有几个要注意的几个问题?
1.什么是回调函数?
简单说就是,使用一个函数,让另一个函数来调用它,就是回调callback
举个例子,A有把抢,给B,让B开枪杀了自己,A自己不开枪。
2.这个then是干什么用的,promise是干什么的?
因为每个程序员的回调名不一样,回调的方式很多,例如上面一开始是用success和fail,来表示响应是否成功,但是有些人用successFn和failFn,或者别的什么来表示同样的东西,难道我们用的时候要从上往下看,一点点找吗?这个太蠢了。所以要引入promise
具体使用方法如下:
在ajax.then(‘success’,'faile'),success和fail中可以直接写代码,默认第一个就是响应成功的时候,第二个是不成功。
优点1.不需要给success和fali赋值
优点2.ajax.then().then()表示进行完第一个then然后使用第一个then的返回值,当作第二个then的传入参数,表示一个链式操作
优点3.返回的requestText是一个对象,本身应该是一个字符串,但是content-type:text/json,会自动将字符串转换成对象。方便操作。
6.Promise对象
return new Promise(function(resolve,reject){
//写代码
}
这句话要被背下来
从上面的例子,我们可以看出Promise对象接收一个函数,并返回一个带有then属性的hash,then也是接受2个函数,并返回一个带then的hash
resolve :表示成功了就调这个
reject:表示失败了就调这个