Jesse James Garrett 讲如下技术取名叫做 AJAX:异步的 JavaScript 和 XML
- 使用 XMLHttpRequest 发请求
- 服务器返回 XML 格式的字符串
- JS 解析 XML,并更新局部页面
如何发请求
- 用 form 可以发请求,但是会刷新页面或新开页面
<body>
<form action="xxx" method="post">
<input type="password" name="password">
<input type="submit">
</form>
</body>
- 用 a 可以发 get 请求,但是也会刷新页面或新开页面
<body>
<a href="//www.greatytc.com/xxx">click</a>
</body>
- 用 img 可以发 get 请求,但是只能以图片的形式展示
<body>
<script>
var image = document.createElement('img')
image.src = '//www.greatytc.com/xxx'
document.body.appendChild(image)
image.onload = function(){
console.log('success')
}
image.onerror = function(){
console.log('fail')
}
</script>
</body>
- 用 link 可以发 get 请求,但是只能以 CSS、favicon 的形式展示
<body>
<script>
var link = document.createElement('link')
link.rel = 'stylesheet'
link.href = '//www.greatytc.com/xxx'
document.head.appendChild(link)
</script>
</body>
- 用 script 可以发 get 请求,但是只能以脚本的形式运行
<body>
<script>
var script = document.createElement('script')
script.src = '//www.greatytc.com/xxx'
document.body.appendChild(script)
</script>
</body>
用 XMLHttpResquest 请求
<script>
myButton.addEventListener('click',(e)=>{
let request = new XMLHttpResquest()
request.onreadystatechange = ()=>{
if(request.readyState = 4){
if(request.status >= 200 && request.status <300){
console.log(request.responseText)
}else if(request.status >= 400){
console.log('请求失败')
}
}
}
request.open('post','//www.greatytc.com/xxx')
request.send()
})
</script>
同源策略和CORS跨域
只有 协议+端口+域名 一模一样才允许发 AJAX 请求。
比如: jack.com:8001 网站向 frank.com:8002 发起 AJAX 请求,
那么需要在 frank.com:8002 的后端添加代码:
response.serHeader('Access-Control-Allow-Orign','http://frank.com:8001')
才能够成功。
...
if(path === '//www.greatytc.com/xxx'){
response.statusCode = 200
response.setHeader('Content-Type','text/jason;charest=utf-8')
response.setHeader('Access-Control-Allow-Orign','http://frank.com:8001')
response.write(`
{
"note"{
"to": "小方",
"from": "小谷",
"note": "Hello"
}
}
`)
response.end()
}esle if(...){
...
}
...
JS操作请求与响应
1.请求第一部分
XMLHttpRequest.open() 可以配置请求的方法,host,路径。
2.设置请求第二部分请求头
XMLHttpRequest.setRequestHeader() 是设置HTTP请求头部的方法。此方法必须在 open()
方法和 send()
之间调用。如果多次对同一个请求头赋值,只会生成一个合并了多个值的请求头。
语法:
myReq.setRequestHeader(header, value);
<script>
myButton.addEventListener('click',(e)=>{
let request = new XMLHttpResquest()
request.onreadystatechange = ()=>{
if(request.readyState = 4){
if(request.status >= 200 && request.status<300){
console.log(request.responseText)
}else if(request.status >= 400){
console.log('请求失败')
}
}
}
request.open('post','//www.greatytc.com/xxx')
request.setRequestHeader('frank','18')
request.send()
})
</script>
可以在开发者工具看到请求头为 frank : 18
设置Content-Type:
request.setRequestHeader('Content-Type','x-www-form-urlencoded')
3.设置请求第四部分
XMLHttpRequest.send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。
<script>
myButton.addEventListener('click',(e)=>{
let request = new XMLHttpResquest()
request.onreadystatechange = ()=>{
if(request.readyState = 4){
if(request.status >= 200 && request.status <300){
console.log(request.responseText)
}else if(request.status >= 400){
console.log('请求失败')
}
}
}
request.open('post','//www.greatytc.com/xxx')
request.send('设置第四部分内容')
})
</script>
4.获取请求的响应
XMLHttpRequest.getAllResponseHeaders() 方法返回所有的响应头。
或者XMLHttpRequest.getAllResponseHeaders() 方法返回所有的响应头。
var myHeader = getResponseHeader(name)
status
: 200
statusText
: OK
responseText
: 响应的第四部分
封装和使用
window.jQuery.ajax = function(method,url,body,successFn,failFn){
let request = new XMLHttpResquest()
request.onreadystatechange = ()=>{
if(request.readyState = 4){
if(request.status >= 200 && request.status <300){
successFn.call(undefined,request.responseText)
}else if(request.status >= 400){
failFn.call(undefined,request)
}
}
}
request.open(method,url)
request.send(body)
}
myButton.addEventListener('click',(e)=>{
winsow.jQuery.ajax(
'post',
'//www.greatytc.com/xxx',
'a=1',
()=>{conosle.log(1)},
()=>{conosle.log(2)}
)
})
// 传入 method url body successFn failFn 的值
做一点优化
window.jQuery.ajax = function(options){
let method = options.method
let url = options.url
let body = options.body
let successFn = options.successFn
let failFn = options.failFn
let request = new XMLHttpResquest()
request.onreadystatechange = ()=>{
if(request.readyState = 4){
if(request.status >= 200 && request.status <300){
successFn.call(undefined,request.responseText)
}else if(request.status >= 400){
failFn.call(undefined,request)
}
}
}
request.open(method,url)
request.send(body)
}
myButton.addEventListener('click',(e)=>{
window.jQuery.ajax({
method: 'post',
url: '//www.greatytc.com/xxx',
body: 'a=1',
successFn: (x)=>{conosle.log(1)},
failFn: (x)=>{conosle.log(2)}
})
})
如果 successFn 需要传两个参数
...
successFn: (x)=>{
f1.call(undefined,x)
f2.call(undefined,x)
},
...
传 header
...
headers: {
'Content-Type':'application/x-www-form-urlencoded',
'frank': '18'
}
...
// window.jQuery.ajax 调整
window.jQuery.ajax = function(options){
let method = options.method
let url = options.url
let body = options.body
let successFn = options.successFn
let failFn = options.failFn
let headers = options.headers
let request = new XMLHttpResquest()
request.onreadystatechange = ()=>{
if(request.readyState = 4){
if(request.status >= 200 && request.status <300){
successFn.call(undefined,request.responseText)
}else if(request.status >= 400){
failFn.call(undefined,request)
}
}
}
request.open(method,url)
for(let key in headers){
let value = headers[key]
request.setRequestHeader(key,value)
} // 遍历 headers 获取 key 和 value
request.send(body)
}
对是否传两个参数做一个判断
window.jQuery.ajax = function(options){
// 假如传了两个参数,做一个判断
let url
if(arguments.length === 1){
url = options.url
}else if(arguments === 2){
url = argumrnts[0]
options = argumrnts[1]
}
let method = options.method
let url = options.url
let body = options.body
let successFn = options.successFn
let failFn = options.failFn
let headers = options.headers
let request = new XMLHttpResquest()
request.onreadystatechange = ()=>{
if(request.readyState = 4){
if(request.status >= 200 && request.status <300){
successFn.call(undefined,request.responseText)
}else if(request.status >= 400){
failFn.call(undefined,request)
}
}
}
request.open(method,url)
for(let key in headers){
let value = headers[key]
request.setHeader(key,value)
}
request.send(body)
}
Promise
简化代码,
myButton.addEventListener('click',(e)=>{
window.jQuery.ajax({
method: 'post',
url: '//www.greatytc.com/xxx',
}).then(
(request.responseText)=>{console.log(request.responseText)},
(request)=>{console.log(error)}
)
})
// 直接在后面跟 then ,第一个参数表示成功后执行的函数,第二个参数表示失败执行的函数
// 可以继续跟 then 再一次对结果进行处理 then中文含义就是 然后
myButton.addEventListener('click',(e)=>{
window.jQuery.ajax({
method: 'post',
url: '//www.greatytc.com/xxx',
}).then(
(request.responseText)=>{console.log(request.responseText)},
(request)=>{console.log(error)}
)
}).then(
(上一次处理结果)=>{console.log(上一次处理结果)},
(request)=>{console.log(error2)}
)
window.jQuery.ajax = function(options){
return new Promise(function(resolve,reject){
let url
if(arguments.length === 1){
url = options.url
}else if(arguments === 2){
url = argumrnts[0]
options = argumrnts[1]
}
let method = options.method
let url = options.url
let body = options.body
let headers = options.headers
let request = new XMLHttpResquest()
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.open(method,url)
for(let key in headers){
let value = headers[key]
request.setHeader(key,value)
}
request.send(body)
})
}
// Promise接收一个函数,返回一个promise对象,有一个 then 的属性。