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,第一个参数是要发送的消息,第二个参数是接收消息的窗口
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351