Ajax 与跨域请求方式

  • XMLHttpRequest对象
  • XMLHttpRequest 2级
  • 进度事件
  • 跨源资源共享
  • 其他跨域技术

Ajax,即 Asynchronous JavaScript + XML,能够向服务器取得数据而无需重新刷新页面。Ajax 技术的核心是XMLHttpRequest对象,使用XHR对象取得新数据,再通过DOM将新数据插入到页面中。XHR属性包括:

  • readyState 请求/响应过程的当前活动阶段
  • responseText 作为响应主体被返回的文本
  • status 响应的 HTTP 状态
  • statusText HTTP 状态的说明

只要readyState的值由一个值变为另一个值,都会触发一次onreadystatechange事件

var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function() {
     if(xhr.readyState == 4){
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
            alert(xhr.responseText)
        } else {
            alert("Request was unsuccessful:" + xhr.status)
        }
    }
}
xhr.open("get", "example.txt", true)
xhr.send(null)

使用XHR时,要调用的第一个方法是open(),接收三个参数,要发送的请求类型,请求的URL和表示是否异步发送请求的布尔值。

xhr.open("get", "example.php", false) //启动一个针对 example.php 的 GET请求
xhr.send(null)

send()方法接收一个参数,即要作为请求主体发送的数据,如果不需要通过请求发送数据,则必须传入null


HTTP头部信息,默认情况下,在发送XHR请求的同时,还会发送下列头部信息:

  • Accept 浏览器能够处理的内容类型
  • Accept-Charset浏览器能显示的字符集
  • Accept-Language 浏览器能够处理的压缩编码
  • Connection 浏览器与服务器之间的连接类型
  • Cookie 当前页面设置的任何Cookie
  • Host 发出请求的的页面所在域
  • Referer 发出请求的页面的 URI
  • User-Agent 浏览器的用户代理字符串

使用setRequestHeader()方法可以设置自定义请求头部信息,方法接收两个参数:头部字段名称和头部字段值,要成功发送请求头部信息,必须在调用open()方法之后且调用send()方法之前调用setRequestHeader()。调用XHR对象的getResponseHeader()方法并传入头部字段名称,可以取得相应的相应头部信息,调用getAllResponseHeaders()可以取得包含所有头部信息的长字符串。


GET用于向服务器查询某些信息,将查询字符串参数追加到 URL 的末尾,将信息发送给服务器。

// 向现有URL的末尾添加字符串查询参数
function addURLParam(url, name, value) {
    url += (url.indexOf("?") == -1 ? "?" : "&")
    url += encodeURIComponent(name) + "=" + encodeURIComponent(value)
    return url
}

POST请求用于向服务器发送应该被保存的数据,将数据作为请求的主体提交

HTTP请求方法


新版的XMLHttpRequest做了一些改进

  • Ajax 操作用来传递表单数据,FormData能够序列化表单,创建与表单格式相同的数据
var data = new FormData()
data.append("name", "siyuan")
  • 可以设置 HTTP 请求的时限,将最长等待事件设置为3000毫秒,过了这个时限,自动停止 HTTP 请求,触发相应的回调函数
xhr.timeout = 3000
xhr.ontimeout = function(event) {
    alert("请求超时")
}
  • 可以实现跨域请求,请求不同域名下的数据
  • 可以上传文件
  • 获取服务端的二进制数据,overrideMimeType()方法重写XHR响应的MIME类型
  • 获得数据传输的进度信息,与progress事件相关的五个事件,可以分别指定回调函数,load,loadstart,loadend,abort,error,可以分别指定回调函数

XMLHttpRequest Level 2


跨域资源共享

默认情况下,XHR对象只能访问与包含它的页面位于同一个域中的资源,实现合理的跨域请求对开发某些浏览器的应用程序至关重要。

  • CORS
    跨域资源共享CORS,定义了在必须访问跨域资源时,使用自定义的HTTP头部让浏览器与服务器进行通信,决定请求或响应是应该成功,还是应该失败。浏览器将CORS请求分为简单请求和非简单请求,只要同时满足以下两个条件,就属于简单请求:
    1)请求方法是HEADGETPOST之一
    2)HTTP的头信息不超过以下字段:AcceptAccept-LanguageContent-LangugaeContent-Type只限于application/x-www-form-urlencodedmultimultipart/form-datatext/plainLast-Event-ID
    简单请求与非简单请求的处理

  • JSONP
    JSONP 是通过动态<script>元素,使用时为src 属性指定一个跨域url,有能力不受限制地从其他域中加载资源。JSONP是有效的JavaScript代码,在请求完成后,JSONP 响应加载到页面中以后,会立即执行。JSONP由回调函数和数据组成,回调函数是在响应到来时应该在页面中调用的函数,回调函数的名字一般在请求中指定,数据就是传入回调函数中的JSON数据。服务器收到请求后,将数据放在回调函数的参数位置返回。JSONP 从其他域中加载代码执行,如果其他域不安全,会在响应中夹带一些恶意代码,此时只能完全放弃 JSONP 调用。

function handleResponse(response) {
}
var srcipt = document.createElement("script")
script.src = "http://freegeoip.net/json/?callback=handleResponse"
document.body.insertBefore(script, document.body.firstChild)
  • Comet
    Comet是一种服务器向页面推送数据的技术,能够让信息实时地被推送到页面上,非常适合处理体育比赛的分数和股票报价。有两种实现Comet的方式:长轮询长轮询是指页面发起到服务器的请求,服务器保持连接打开,直到有数据可发送,发送完数据之后,浏览器关闭连接,随即发送一个到页面的新请求,这个过程在页面打开期间一直持续不断。HTTP流在页面的整个生命周期只使用一个HTTP连接,浏览器向服务器发送一个请求,服务器保持连接打开,周期性地向浏览器发送数据。所有浏览器都支持长轮询,只有部分浏览器原生支持HTTP流。服务器发送事件SSE是一种实现Comet交互的浏览器API,即支持长轮询,也支持HTTP流,用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。
function createStreameingClient(url, progress, finished) {
    //接收三个参数:要连接的url, 接收到数据时调用的函数, 关闭连接时调用的函数
    var xhr = new XMLHTtpRequest()
    var received = 0
    xhr.open("get", url, true)
    xhr.onreadystatechange = function() {
        var res
        if (xhr.readyState == 3) {
            res = xhr.responseText.substring(res)
            received += res.length
            progress(res)
        } else if (xhr.readyState == 4) {
            finished(xhr.responseText)
        }
    }
    xhr.send(null)
    return xhr
}
  • Web Sockets
    Web Sockets能够在一个单独的持久连接上提供全双工、双向通信,在JavaScript 中创建了Web Sockets之后,会有一个HTTP请求发送到浏览器以发起连接,在取得服务器的响应之后,建立的连接会使用HTTP 协议升级为 Web Sockets协议,能够在客户端和服务器之间发送非常少量的数据,不必担心HTTP那样的字节级开销。未加密的连接是ws://,加密的连接是wss://。必须给Web Sockets构造函数传入绝对URL,同源策略对Web Socket不适用,可以通过它打开任何站点的连接。
var socket = new WebSocket("ws://example.com/server.php")
socket.send("hello world")
socket.close()

WebSocket对象还有open,error,close事件,在连接生命周期的不同阶段触发,适用于聊天室等。对于未被授权的系统有权访问某个资源的情况,称为跨站脚本攻击,可以通过 1)要求以SSL连接来访问可以通过XHR请求的资源,2)要求每一次请求都要附带经过相应算法计算得到的验证码。


此外,如果非同源,共有三种行为受到限制:

  • Cookie、LocalStorage、IndexDB无法读取
  • DOM无法获得
  • Ajax请求不能发送

对于Cookie和iframe的跨域问题,在一级域名相同,二级域名不同的情况下,可以通过设置相同document.domain,两个网页就可以共享Cookie。

对于网页不同源,就无法拿到对方的DOM的情况,如对于iframe、window.open()方法打开的窗口,与父窗口无法通信。

  • 片段标识符,URL后面的#为片段标识符,只改变片段标识符,页面不会重新刷新。将父窗口的信息写入子窗口的片段标识符,子窗口通过haschange事件得到通知。
//父窗口
var src = originURL + '#' + data
document.getElementById('parentFrame').src = src
window.onhaschange = checkMessage

 //子窗口
function checkMessage() {
    var message = window.location.hash
                ...
}
  • 浏览器窗口的window.name属性,前一个网页设置了这个属性,后一个网页可以读取它
  • window.postMessage跨文档通信API,第一个参数是要发送的消息,第二个参数是接收消息的窗口
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容