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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 该文章介绍了AJAX技术的基本使用方法,包括GET和POST请求的模拟,并探讨了浏览器同源策略及其对跨域请求的影响,同时还提出了JSONP和CORS作为解决跨域问题的方案。

引言

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以及跨域的一些信息就讲到这里啦!如有疑问欢迎评论区评论或私信我交流~

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

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

相关文章
|
7月前
|
前端开发
解决前端ajax跨域请求不携带cookie信息JSESSIONID的问题
解决前端ajax跨域请求不携带cookie信息JSESSIONID的问题
|
JSON 前端开发 JavaScript
前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(一)
前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(一)
593 0
|
3月前
|
前端开发 API UED
Python后端与前端交互新纪元:AJAX、Fetch API联手,打造极致用户体验!
Python后端与前端交互新纪元:AJAX、Fetch API联手,打造极致用户体验!
110 2
|
2月前
|
前端开发 JavaScript
回顾前端页面发送ajax请求方式
回顾前端页面发送ajax请求方式
38 18
|
5月前
|
前端开发 API UED
Python后端与前端交互新纪元:AJAX、Fetch API联手,打造极致用户体验!
【7月更文挑战第15天】Python后端(Django/Flask)与前端通过AJAX或Fetch API实现异步交互,提升Web应用体验。Python提供强大的后端支持,AJAX用于不刷新页面的数据交换,Fetch API作为现代标准,基于Promise简化HTTP请求。结合两者,构建高效、流畅的交互系统,优化响应速度和用户体验,开启Web开发新篇章。
85 5
|
5月前
|
前端开发 JavaScript API
告别‘老司机’时代,AJAX与Fetch API让你的前端与Python后端无缝对接!
【7月更文挑战第14天】前端与后端交互的关键技术是AJAX和Fetch API。AJAX允许不刷新页面更新内容,而Fetch API提供了Promise基
69 0
|
6月前
|
JSON 前端开发 JavaScript
前端Ajax、Axios和Fetch的用法和区别笔记
前端Ajax、Axios和Fetch的用法和区别笔记
108 2
|
前端开发
Echarts实战案例代码(21):front-endPage的CJJTable前端分页插件ajax分页异步加载数据的解决方案
Echarts实战案例代码(21):front-endPage的CJJTable前端分页插件ajax分页异步加载数据的解决方案
93 0
|
7月前
|
JSON 前端开发 JavaScript
前端知识笔记(三十七)———Django与Ajax
前端知识笔记(三十七)———Django与Ajax
54 0
|
7月前
|
JSON 前端开发 JavaScript
前端知识笔记(二)———Django与Ajax
前端知识笔记(二)———Django与Ajax
64 0