跨越跨域大山,前端不得不知道的Ajax

本文介绍了AJAX的基本使用,包括模拟GET和POST请求以及封装简易AJAX函数。同时深入探讨了浏览器的同源策略,解释了为何存在这一策略及其限制,并提出了解决跨域问题的JSONP和CORS两种方法。最后,总结了跨域的定义和实现方式。
摘要由CSDN通过智能技术生成

引言

ajax对于前端来说是一个特别基础也特别实用的一个功能,基本上我们目前访问的很多网页都有用到 ajax 的功能。接下来开始讲解关于AJAX请求,以及关于跨域的一些内容。

正文

一、AJAX请求

Ajax ,即 Asynchronous Javascript And XML(异步JavaScript和XML)。

在实现 Ajax 之前,我们先来了解下 XMLHttpRequestXMLHttpRequest 是网页实现 AJAX 最主要的一个 API 。可能有很多同学知道 AJAX ,也用过 AJAX ,但是却不知道它是基于 XMLHttpRequest 来实现的。

那么接下来我们用 XMLHttpRequest 这个 API 来模拟一个 getpost 请求。

1、模拟get和post请求

(1)模拟get请求:

/**
 * 使用xhr模拟实现GET请求
 */
const xhr = new XMLHttpRequest();
xhr.open('GET', '/test.json', true); //false表示同步请求,true表示异步请求
xhr.onreadystatechange = function () {
    // 这里的函数异步执行
    if(xhr.readyState === 4){
        if(xhr.status === 200){
            // console.log(
            //     JSON.parse(xhr.responseText)
            // );
            alert(xhr.responseText);
        }
    }
}
// 因为是get请求,所以只要发送null就好
xhr.send(null);

(2)模拟post请求:

/**
 * 使用xhr模拟实现post请求
 */
const xhr = new XMLHttpRequest();
//模拟请求一个登录接口
xhr.open('POST', '/login', true); //false表示同步请求,true表示异步请求
xhr.onreadystatechange = function(){
    if(xhr.readyState === 4){
        if(xhr.status === 200){
            console.log(
                JSON.parse(xhr.responseText)
            );
            alert(xhr.responseText);
        }else{
            console.log('其他情况');
        }
    }
}

const postData = {
    userName: 'zhangsan',
    password: 'xxx'
}

xhr.send(JSON.stringify(postData));

2、封装一个简易的AJAX

function ajax(url){
    const p = new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.onreadystatechange = function(){
            //状态码的解析详细看第二点
            if(xhr.readyState === 4){
                if(xhr.status === 200){
                    resolve(
                        JSON.parse(xhr.responseText)
                    );
                }else if(xhr.status === 404){
                    reject(new Error('404 not found'));
                }
            }
        }
        xhr.send(null);
    });
    return p;
}

const url = '你的json数据路径';
ajax(url)
.then(res => console.log(res))
.catch(err => console.error(err));

二、状态码

看完上面的模拟过程之后,我们来讲解其中的几个知识点。

1、xhr.readyState

readyState状态值readyState含义
0(未初始化)- 还没有调用send()方法
1(载入)- 已调用send()方法,正坐在发送请求
2(载入完成)- send()方法执行完成,已经接收到全部响应内容
3(交互)- 正在解析响应内容
4(完成)响应内容解析完成,可以在客户端调用

2、xhr.status

status状态值status含义
2xx表示成功处理请求,如200
3xx需要重定向,浏览器直接跳转,如301 302 304
4xx客户端请求错误,如404 403
5xx服务器端错误

三、跨域

1、同源策略

(1)同源策略是什么

同源策略是浏览器自带的一种安全策略,它是指网址中的协议域名端口三个都相同时才能互相访问,即若协议、域名、端口有一个不相同时,浏览器禁止页面加载或执行与自身不同域的脚本。

(2)为什么浏览器会有同源策略?

因为如果没有同源策略,别人就可以轻松的获取我们网站的 cookie 信息,或是对网页进行 DOM 操作;

这是一件非常恐怖的事情,尤其是 cookie 信息,它里面存在着 sessionID ,这是与服务端的 session 会话的重要凭证,如果被别人得到了 cookie ,有很大可能会造成数据被盗取等后果。

(3)同源策略限制内容有哪些?

  • 存储在浏览器中的数据,如 localStroageCookieIndexedDB 不能通过脚本跨域访问;
  • 不能通过脚本操作不同域下的 DOM
  • 不能通过 ajax 请求不同域的数据。

(4)加载图片、js和css时可以无视同源策略

<img src = 跨域的图片地址 />
<link href = 跨域的css地址/>
<script src = 跨域的js地址></script>

如以上代码所示,当我们在加载以上类型的 图片、css和js 时,可以无视同源策略。因为像 图片、css文件和js文件 一般可使用 cdn 来进行缓存,而 cdn 一般是外域。同时, js 文件也可以通过 JSONP 来实现跨域。

2、跨域解决方案

(1)跨域是什么

  • 所有的跨域,都必须经过 server 端允许和配合;
  • 未经 server 端允许就实现跨域,说明浏览器有漏洞,是一种危险信号。

(2)解决跨域的方式

1)JSONP(客户端操作)

① JSONP的原理

JSONP(JSON with Padding)是数据格式 JSON 的一种“使用模式”,可以让网页从别的网域要数据。

根据 XmlHttpRequest 对象受到同源策略的影响,而利用

JSONP 抓到的数据并不是 JSON ,而是任意的 JavaScript ,用 JavaScript 解释器运行而不是用 JSON 解析器解析。

所以,通过 Chrome 查看所有 JSONP 发送的 Get 请求都是 js 类型,而非 XHR

② JSONP包含两部分:回调函数和数据

回调函数是当响应到来时要放在当前页面被调用的函数。

数据就是传入回调函数中的 json 数据,也就是回调函数的参数了。

function handleResponse(response){
 console.log('The responsed data is: '+response.data);
}
var script = document.createElement('script');
script.src = 'http://www.baidu.com/json/?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);
/*handleResonse({"data": "zhe"})*/
//原理如下:
//当我们通过script标签请求时
//后台就会根据相应的参数(json,handleResponse)
//来生成相应的json数据(handleResponse({"data": "zhe"}))
//最后这个返回的json数据(代码)就会被放在当前js文件中被执行
//至此跨域通信完成

③ 缺点:

  • 只能使用Get请求
  • 不能注册successerror等事件监听函数,不能很容易的确定 JSONP 请求是否失败。
  • JSONP 是从其他域中加载代码执行,容易受到跨站请求伪造的攻击,其安全性无法确保。
2)CORS(服务器操作)

① cors的原理

CORS (Cross-Origin Resource Sharing),即跨域资源共享,是一种浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,确保安全的跨域数据传输。现代浏览器使用 CORSAPI 容器如 XMLHttpRequest 来减少 HTTP 请求的风险来源。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。

cors 的跨域方法一般是服务端进行操作,服务端需要设置以下 http header

//设置允许跨域的域名称,不建议直接写“*”
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");

//填写允许跨域的http请求方法
//当 method = OPTIONS 时, 属于预检(复杂请求), 当为预检时, 可以直接返回空响应体, 对应的 http 状态码为 204
response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");

//设置需要支持的跨域请求头,如果设置为*,表明服务器支持所有头信息字段;也可设置为X-Request-With和Content-Type
response.setHeader("Access-Control-Allow-Headers", "X-Request-With, Content-Type");
// 服务器收到请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

//表示具体请求中的媒体类型信息
response.setHeader("Content-Type", "application/json;charset=utf-8");

//设置预检结果的缓存, 单位(秒)
response.setHeader("Access-Control-Max-Age", 86400);

/*如果需要支持 cookies,
 *Access-Control-Allow-Origin 不能设置为 *,
 *并且 Access-Control-Allow-Credentials 需要设置为 true
 *(注意前端请求需要设置 withCredentials = true)
*/
response.setHeader("Access-Control-Allow-Credentials", "false");

结束语

以上文章浅谈了 ajax 以及常用的跨域方案,没有深究到很细节层面的内容。希望对大家有帮助!

关于Ajax以及跨域的一些信息就讲到这里啦!如有疑问欢迎评论区评论或私信我交流~

  • 关注公众号 星期一研究室 ,不定期分享学习干货

  • 如果这篇文章对你有用,记得点个赞加个关注再走哦~

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值