AJAX的出现与跨域处理
如何发请求在前端的世界里也逛荡了不少日子了,目前已经get到大约5种发起请求的方式,主流的、非主流的。
可是
AJAX出现浏览器和服务器交互模式 V1.0在
我称这种交互方式是 V1.0,此时还是以获取资源为导向。后来随着时代的发展,人们日益增长的文化需求成为了社会的主要矛盾……有一天,小明看了一篇报道,他只是想在下面评论一下,发表对实事的亲切问候,问候完了,唉,你给我刷新页面干啥,我只是想评论一下啊。
大概那是网民们第一次对 良好的用户体验 提出了要求。后来的苹果爸爸,把大家惯坏了,天天嚷着 "你这产品用户体验太差了"…… 彼时,微软还是对web做出了很大的贡献的。 交互模式2.0大约1999年,微软发布 AJAX 可以看出IE当时还是很猛的,随着IE 6.0 市场份额进一步扩大,IE已经把火狐整的半死不活,放眼整个浏览器市场,微软是当之无愧的王者,后来微软就把浏览器团队解散了……不得不说这是一波神操作,能与之媲美的操作大概只有 既然 XMLHttpRequest
古代的操作的是:
什么是XML,可扩展标记语言。 以上是最初的用法,用的是 let request = new XMLHttpRequest() //实例化XMLHttpRequest对象 request.onreadystatechange = () => { if (request.readyState === 4) { console.log('请求和响应都完毕了') if (request.status >= 200 && request.status <= 300) { console.log('说明请求成功了') console.log(request.responseText) let parser = new DOMParser() let xmlDoc = parser.parseFromString(request.responseText,"text/xml") //用parser解析request.responseText let c = xmlDoc.getElementsByTagName('body')[0].textContent console.log(c) } else if (request.status >= 400) { console.log('说明请求失败了') } } } request.open('GET','/xxx') //配置request request.send() 服务器端的对应代码片段如下 ... response.statusCode = 200 response.setHeader('Content-Type','text/xml;charset=utf-8') response.write(` <note> <to>木木</to> <from>少少</from> <heading>你好哇</heading> <body>好久不见啊</body> </note> `) response.end() ... 本地模拟的话,一定要记得开俩不同的端口 node server.js 8001 node server.js 8002 XMLHttpRequest实例的详解正如上面的前端代码片段写的一样,主要用到了
习惯用 JSON后来一个美国程序员道格拉斯·克罗克福特发明了 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于 JavaScript Programming Language,Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C,C++,C#,Java,JavaScript,Perl,Python等)。 这些特性使JSON成为理想的数据交换语言。 以上是JSON官网的简介,可以看出它是一门全新的语言,不是JavaScript的子集。
let string = request.responseText let json = window.JSON.parse(string) //string 要符合JSON的格式 以上是JSON解析部分的代码。 此时服务器端代码是 response.statusCode = 200 response.setHeader('Content-Type','text/json;charset=utf-8') response.write(` { "note" : { "to" : "木木","from" : "少少","heading" : "你好哇","content" : "好久不见啊" } } `)
4. CORS
<button id="myButton">点我</button> <form action="https://www.baidu.com" method="get"> <input type="password" name="password"> <input type="submit" value="提交"> </form> 上述请求响应都没有问题 ... request.open('GET','http://www.baidu.com') ...
原页面用 form 提交到另一个域名之后,原页面的脚本无法获取新页面中的内容,所以浏览器认为这是安全的。 那么如何让
request.open('GET','http://wushao.com:8001/xxx') //配置request
response.setHeader('Access-Control-Allow-Origin','http://shaolin.com:8002') 一定要注意是谁去访问谁,8001去访问8002,那么8001的前端代码要告诉8002的后端代码,咱们是一家人,你和浏览器说说别让它禁我了。 AJAX一些其他知识既然可以发请求,那么请求头的四部分如何获得的,响应的四部分又是如何获得呢 获得请求和响应头
request.open('GET','http://shaolin.com:8002/xxx')// 请求的第一部分 request.setRequestHeader('Content-Type','x-www-form-urlencoded')//请求的第二部分 request.setRequestHeader('wushao','18') //请求的第二部分 request.send('我要设置请求的第四部分') //请求的第四部分 request.send('name=wushao&password=wushao') //请求的第四部分 对应的典型的http请求四部分 GET /xxx HTTP/1.1 HOST: http://shaolin.com:8002 Content-Type: x-www-form-urlencoded wushao: 18 name=wushao&password=wushao
request.status //响应的第一部分 200 request.statusText //响应的第一部分 OK request.getAllResponseHeaders //响应的第二部分,这个方法好啊,全部的响应头 request.getResponseHeader('Content-Type') //响应的第二部分具体的 request.responseText //响应的第四部分 对应的典型的http响应的四部分 HTTP/1.1 200 OK Content-Type: text/json;charset=utf-8 { "note" : { "to" : "木木","content" : "好久不见啊" } } 回顾一下各个status对应的意思 100 200 === OK,请求成功 301 === 被请求的资源已永久移动到新位置 302 === 请求临时重定向,要求客户端执行临时重定向 304 === 和上次请求一样,未改变 403 === 服务器已经理解请求,但是拒绝访问 404 === 请求失败,服务器上没有这个资源 502 === 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。 503 === Service Unavailable 由于临时的服务器维护或者过载,服务器当前无法处理请求。 练习一下JQuery封装AJAX
这是一个很简陋的效果,首先我还是把jq假设的很简单,就是一个window的属性,请轻喷…… window.jQuery = function (nodeOrSelector) { let nodes = {} nodes.addClass = function () {} nodes.html = function () {} return nodes } window.jQuery.ajax = function (options) { let url = options.url let method = options.method let headers = options.headers let body = options.body let successFn = options.successFn let failFn = options.failFn let request = new XMLHttpRequest() //实例化XMLHttpRequest对象 request.open(method,url) 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) { successFn.call(undefined,request.responseText) } else if (request.status >= 400) { failFn.call(undefined,request) } } } request.send(body) } 以上就是jq对ajax的简陋的封装,ajax()方法接受一个对象作为参数,这个对象有很多键。这些键就是http请求的头的各个部分,以及一个成功函数和一个失败函数。 myButton.addEventListener('click',(e) => { window.jQuery.ajax ({ url: '/xxx',method: 'POST',headers: { 'content-type': 'application/x-www-form-urlencoded','wushao': '18' },body: 'a=1&b=6',successFn: (x) => { ... },failFn: (x) => { ... } }) }) 以上就是简化后的使用方法,给button绑定事件的时候,函数体直接就是ajax()
let url if (arguments.length === 1) { url = options.url } else if (arguments.length === 2) { url = arguments[0] options = arguments[1] } let method = options.method let headers = options.headers let body = options.body let successFn = options.successFn let failFn = options.failFn 加了一点,判断ajax()的参数个数。
//Promise这个对象呢,大概长这个样子,真实面目我是没见过 //简单的写一下promise window.Promise = function (fn) { //...一些其他代码 return { then: function () {} } } Promise这个构造函数呢,又会返回一个函数,这个返回的函数一个then属性,value又是一个函数。处处都体现着函数是第一公民的地位!!! //第一步的代码改造成这样,第一步用到了ES6的解构赋值法 window.jQuery.ajax = function ({url,method,body,headers}) { return new Promise(function (resolve,reject) { let request = new XMLHttpRequest() request.open(method,url) 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) }) } 关于解构赋值:ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring) //经过上面这么一折腾,可以很简单的使用了 myButton.addEventListener('click',(e) => { let promise = window.jQuery.ajax({ url: '/xxx',method: 'get','wushao': '18' } }) promise.then( (responseText) => { console.log(responseText) },(request) => { console.log(request) } ) }) 注意then可以传入两个函数,第一个函数表示成功了执行这个,第二个函数表示失败了执行这个,而且可以进行链式调用,一直点下去。
myButton.addEventListener('click',(e) => { $.ajax({ url: '/xxx',type: 'GET',}).then( (responseText) => { console.log(responseText) return responseText },(request) => { console.log('error') return '已经处理' } ).then( (responseText) => { console.log(responseText) },(request) => { console.log(error2) } ) }) 链式调用的意思就是:成功函数成功了,就执行第二个then的第一个函数;成功函数失败了,就执行第二个then的第二个函数。 完整代码详见我的gitHub (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |