Ajax和跨域总结

Ajax(JavaScript实现)

简介

Ajax(Async Javascript And Xml):异步Js和Xml,意思就是用Js执行异步网络请求。作用主要是在不重新加载全部网页的情况下,对部分页面进行更新。

创建XMLHttpRequest对象

除了IE5和IE6不支持之外(支持ActiveXObject对象),几乎现在所有的有内建的XMLHttpRequest对象。所以在创建请求对象之前判断下就好了:

let xhr = null;
xhr = window.XMLHttpRequest ? new xmlHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP")
// 或者
if(window.XMLHttpRequest){
    xhr = new XMLHttpRequest()
}else{
    xhr = new ActiveXObject('Microsoft.XMLHTTP')
}

通过open()和send()向服务器发送请求

  • xhr.open(method, url, async)
    这个方法的参数分别是:method请求的类型GET或者POST;URL请求的文件在服务器上的地址;async是否异步请求true或者false(一般不设置为false)。
  • xhr.send():发送请求。
  • xhr.setRequestHeader(header, value):如果是POST的话,要设置发送的HTTP头,然后通过send方法发送内容。参数分别是:发送的头部名称,头部的值。一般都是固定的。
// 向浏览器发送请求
xhr.open('GET', './server.php', true)
// 添加HTTP头(POST方法)
xhr.setRequestHeader('Content-Text', 'application/x-www-form-urlencoded')   
xhr.send()

GET方法不需要参数,POST方法则需要把body参数;如果要想向服务器发送相关的参数,则通过open里面的第二个参数url进行发送,具体实现如下代码:

url = "./filePath?paramName=" + paramValue + ...;

判断准备状态

xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
        ...
    }
}
  • xhr.onreadystatechange方法中,每当readyState改变时,就会触发xhr.onreadystatechange事件。
  • readyState属性:存有XMLHttpRequest的状态信息。0:请求未初始化;1:服务器链接已经建立;2:请求已经接受;3:请求处理中;4:请求已完成,且响应已就绪。一共有5个状态,所以onreadystatechange事件会被触发5次。
  • 实际上onreadystateschange是通过回调函数实现的,即:每当readyState的状态改变时,这个回调函数就会被执行。
  • status属性:表示响应的结果。

总的代码如下:

document.getElementById('btn').onclick = function () {
// 创建请求对象(先判断浏览器类型)
// var xhr = null;
// if (window.XMLHttpRequest) {
//     xhr = new XMLHttpRequest()
// } else {
//     xhr = new ActiveXObject('Microsoft.XMLHTTP')
// }
xhr = (window.XMLHttpRequest) ? (new XMLHttpRequest()) : (new ActiveXObject('Microsoft.XMLHTTP'))
// 判断响应状态并执行相关的操作
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
        let data = xhr.responseText
        console.log(data);
        document.getElementById('myDiv').innerText = data
    }
}
// 向浏览器发送请求
let url = "./server.txt"
xhr.open('GET', url, true)
// 添加HTTP头(POST方法)
// xhr.setRequestHeader('Content-Text', 'application/x-www-form-urlencoded')
xhr.send(null);
}
异步1.gif

但是,由于在同源策略的作用下,浏览器只能同源的其他域的资源,先看看什么是同源策略~

同源策略/SOP(Same origin policy)

来自百度的解释:

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能(防止CSRF/XSRF攻击:跨站请求伪造)。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。

简单来说,就是浏览器只能请求同源的其他域的资源,即同源的网页才能相互获取资源,而不能访问其他域的资源;但是有一个例外,同源策略不会阻止动态脚本插入到文档中;其中,<script></script>是开放策略;当web网页执行一个脚本之前,会检查是否同源,只有同源才会被执行,非同源则会被拒绝访问。
截取网上的图片说明同源:

image.png

跨域

跨域就是突破同源策略的限制,获取其他源的资源。
非同源主要有三种行为会受到限制:

  • Cookie,LocalStorage和IndexDB无法读取。
  • DOM无法获取。
  • Ajax无法获取。

JSONP

JSONP是实现跨域的常用方法,但是JSONP只能实现GET方法。实际上是是利用了浏览器允许跨域引用JavaScript资源(script标签是开放策略)。

下面举一个例子:我们从360浏览器首页的天气查询获取天气查询的异步请求地址;这里我们实现通过本地localhost服务器跨域请求360的天气查询,来说明JSONP怎么实现跨域。
我们请求资源的地址为:
https://cdn.weather.hao.360.cn/sed_api_weather_info.php?code=101280501&v=2&param=weather&app=hao360&_jsonp=jsonp21&t=2521600
在浏览器中打开这个地址,我们会得到这样的数据:__jsonp21__({...})。
解释:JSONP返回的通常是以函数的形式返回,前面这个__jsonp21__是函数名,所以我们需要在我们的代码中事先准备好名称为__jsonp21__的函数,我们对跨域请求到的数据就是放在这个函数中的,然后动态加载一个script节点,相当于动态读取外域的JavaScript资源,最后就等着接收回调了。

具体代码如下:

 // 请求的地址为:https://cdn.weather.hao.360.cn/sed_api_weather_info.php?code=101280501&v=2&param=weather&app=hao360&_jsonp=__jsonp21__&t=2521600

function __jsonp21__(data) {   // 将要处理了的数据放在这个函数中
    console.log(data);  // 得到的是跨域请求的数据
    let myDiv = document.getElementById('myDiv')  
    myDiv.innerHTML = data.area
}
window.onload = function () { 
    let btn = document.getElementById('btn')
    btn.addEventListener('click', function () {  
        let url = 'https://cdn.weather.hao.360.cn/sed_api_weather_info.php?code=101280501&v=2&param=weather&app=hao360&_jsonp=__jsonp21__&t=2521600'
        let scriptTag = document.createElement('script')    // 动态创建script标签 
        scriptTag.setAttribute('src', url)      // 将其他源的地址设置为动态script的src属性
        // console.log(scriptTag);  // 得到的是script标签
        document.getElementsByTagName('body')[0].appendChild(scriptTag)  // 将动态创建的script标签添加到html页面中
    })
}

注意:数据处理的函数名要跟跨域返回的函数名一样,这样我们通过JSONP请求数据的时候,服务器才能返回数据。
最终结果如下:


跨域1.gif

再句一个例子:
请求地址是http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice

function refreshPrice(data) { 
console.log(data);
}
window.onload = function () {  
    let scriptTag = document.createElement('script')
    let url = 'http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice'
    scriptTag.setAttribute('src', url)
    document.getElementsByTagName('body')[0].appendChild(scriptTag)
}

Ajax(JQuery实现)

在JQuery中,实现Ajax主要是由$.ajax({...})方法实现。方法的常用参数有:

  • async:是否实现异步加载,一般来说,是true。
  • type:GET或者POST。
  • url:发送请求的地址。
  • timeout:设置请求的超时时间。
  • success:请求成功后的回调函数。
  • error:请求失败后的回调函数。
  • jsonp:在一个JSONP请求中重写回调函数的名字,默认为callback,用来重新命名回调我们跨域请求时候的函数名字。这个值用来替代在 "callback=?" 这种 GET 或 POST 请求中 URL 参数里的 "callback" 部分,比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。
  • jsonpCallback:为JSONP请求指定一个回调函数名。
  • dataType:预期服务器返回的数据类型。不指定的话,JQueryhi自动判断。"xml": 返回 XML 文档,可用jQuery处理。

"html": 返回纯文本 HTML 信息;包含的 script 标签会在插入 dom 时执行;"script": 返回纯文本JavaScript代码。不会自动缓存结果。除非设置了"cache"参数。注意:在远程请求时(不在同一个域下),所有POST请求都将转为GET请求。(因为将使用DOM的 script标签来加载);"json": 返回JSON数据;"jsonp": JSONP格式。使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数;"text": 返回纯文本字符串。

用JQuery实现同源的Ajax请求:

$(function () {  
    $('button').on('click', function () {  
        $.ajax({
            url: './server.txt',    // 请求地址
            type: 'GET',    // 请求方式
            async: true,    // 是否异步
            success: function (data) {  
                console.log(data);
            }   // 请求成功后执行的函数
        })
    })
})

实现结果如下:


异步2.gif

用JQuery实现非同源的JSONP跨域请求:

$(function () {  
$('button').on('click', function () {  
    $.ajax({
        url: 'https://cdn.weather.hao.360.cn/sed_api_weather_info.php?code=101280501&v=2&param=weather&app=hao360&_jsonp=__jsonp21__&t=2521600',
        type: 'GET',
        async: true,
        dataType: 'jsonp',
        jsonp: '_jsonp',
        jsonpCallback: '__jsonp21__',
        success: function (data) {  
            console.log(data);
            $('#myDiv').html(data.area)
        },
        error: function (err) {  
            console.log(err);
        }
    })
})
})

实现结果如下:


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

推荐阅读更多精彩内容

  • 一、浏览器的同源策略 1.什么是同源? 所谓“同源”指的是”三个相同“。相同的域名、端口和协议,这三个相同的话就视...
    徐国军_plus阅读 838评论 1 3
  • 前言:对于跨域请求,很早之前就有去了解过,但因为一直关注的都是服务器后端开发,故也就仅仅停留在概念的理解上而没有机...
    ken_ljq阅读 89,754评论 6 128
  • 同源策略 理解跨域首先必须要了解同源策略。同源策略是浏览器上为安全性考虑实施的非常重要的安全策略。何谓同源:URL...
    48892085f47c阅读 722评论 0 6
  • 浏览器在请求不同域的资源时,会因为同源策略的影响请求不成功,这就是通常被提到的“跨域问题”。作为前端开发,解决跨域...
    SCQ000阅读 2,547评论 1 52
  • 禅绕插画设计《菠萝》 首先观察菠萝, 去超市买回或度娘搜索“菠萝” 又搜到了这张简笔画 我们要庆幸活在这个时代,有...
    太婆插画阅读 2,246评论 3 26