前端学习记录~2023.8.10~JavaScript重难点实例精讲~第6章 Ajax

第 6 章 Ajax

  • 前言
  • 6.1 Ajax的基本原理及执行过程
    • 6.1.1 XMLHttpRequest对象
      • (1)XMLHttpRequest对象的函数
      • (2)XMLHttpRequest对象的属性
    • 6.1.2 XMLHttpRequest对象生命周期
      • (1)创建XMLHttpRequest对象
      • (2)建立连接
      • (3)发送请求并传递数据
      • (4)处理响应
    • 6.1.3 Ajax的优缺点
      • (1)优点
      • (2)缺点
  • 6.2 使用Nodejs搭建简易服务器
  • 6.3 使用Ajax提交form表单
    • 6.3.1 通用处理
    • 6.3.2 使用原生Ajax进行提交
      • (1)绑定提交按钮事件
      • (2)创建XMLHttpRequet对象
      • (3)建立连接
      • (4)设置请求头
      • (5)获取数据
      • (6)发送请求
      • (7)处理响应
    • 6.3.3 使用jQuery处理Ajax请求进行提交
    • 6.3.4 使用jQuery序列化form表单进行提交
    • 6.3.5 使用FormData对象进行提交
  • 6.4 关于Ajax请求的get方式和post方式
    • 6.4.1 get方式和post方式的区别
    • 6.4.2 使用get方式和post方式需要注意的点
    • 6.4.3 get方式和post方式的使用场景
      • (1)Ajax使用get方式的场景
      • (2)Ajax使用post方式的场景
  • 6.5 Ajax进度事件
    • (1)load事件
    • (2)progress事件
  • 6.6 JSON序列化和反序列化
    • 6.6.1 JSON序列化
      • (1)JSON.stringify()函数
      • (2)自定义toJSON()函数
      • (3)序列化处理的顺序
    • 6.6.2 JSON反序列化
      • (1)JSON.parse()函数
      • (2)eval()函数
  • 6.7 Ajax跨域解决方案
    • 6.7.1 浏览器同源策略
    • 6.7.2 浏览器跨域限制
    • 6.7.3 Ajax跨域请求场景
    • 6.7.4 CORS
    • 6.7.5 JSONP


前言

本章是第六章Ajax相关的内容。

Ajax是一种流行的前后端数据交互的方式,通过异步请求就可以在不需要刷新页面的情况下,达到局部刷新的效果。

Ajax并非是一种全新的技术,而是由以下技术组合而成:

  • 使用CSS和XHTML做页面呈现
  • 使用DOM进行交互和动态显示
  • 使用XMLHttpRequest对象和服务器进行异步通信
  • 使用JavaScript进行绑定和调用,操作DOM

在学完后,希望掌握下面知识点:

  • Ajax的基本原理及执行过程
  • Nodejs搭建简易服务器
  • Ajax提交form表单
  • Ajax进度事件
  • JSON序列化和反序列化
  • Ajax跨域解决方案

6.1 Ajax的基本原理及执行过程

Ajax的基本原理是通过XMLHttpRequest对象向服务器发送异步请求,获取服务器返回的数据后,利用DOM的操作来更新页面。

下面是Ajax的执行流程:
在这里插入图片描述
其中最核心的部分就是XMLHttpRequest对象。它是一个JavaScript对象,支持异步请求,可以及时向服务器发送请求和处理响应,并且不阻塞用户,达到不刷新页面的效果。

下面重点讲解XMLHttpRequest对象相关知识点。

6.1.1 XMLHttpRequest对象

XMLHttpRequest对象从创建到销毁存在一个完整的生命周期,在生命周期的每个阶段会调用XMLHttpRequest对象的不同函数,在函数中需要通过XMLHttpRequest对象的特定属性来判断函数执行情况。

下面就会记录XMLHttpRequest对象的函数和属性

(1)XMLHttpRequest对象的函数

  1. abort():如果请求已经发送,则停止当前请求
  2. getAllResponseHeaders():获取所有HTTP请求的响应头部,作为键值对返回;如果没有收到回应,则返回null
  3. getResponseHeader("key"):获取特定key的HTTP响应头,没有收到响应或不存在则返回null
  4. open("method","URL","[asyncFlag]","[userName]","[password]"):建立对服务器的调用。method表示请求方式,可以为GETPOSTPUT;URL表示请求路径,绝对路径或相对路径均可;后面三个参数可选,表示是否异步、用户名、密码。asyncFlag=true表示异步,false表示同步,默认为true异步
  5. send(content):向服务器发送请求
  6. setRequestHeader("key","value"):设置请求头属性为key的值为value。在设置请求头之前需要先调用open()函数,设置的header将随着send()函数一起发送

(2)XMLHttpRequest对象的属性

  1. onreadystatechange:状态改变的事件触发器。每个状态改变时都会触发这个事件处理器,通常会调用一个JavaScript函数
  2. readyState:请求的状态。有 5 个可取的值:
    • 0:未初始化,XMLHttpRequest对象已创建
    • 1:open()函数已调用,send()函数未调用,请求还未发送
    • 2:send()函数已调用,HTTP请求已发送到服务器,未收到响应
    • 3:所有响应头接收完成,响应体开始接收但未完成
    • 4:HTTP响应接收完成
  3. responseText:接受的数据文本格式的服务器响应体(不包括响应头)
  4. responseXML:服务器的响应,兼容DOM的XML对象,解析后可得到DOM对象
  5. status:服务器返回的HTTP状态码,用数字表示,如200表示成功,404表示资源未找到
  6. statusText:HttP状态码的文本表示,如200时对应"OK",404时对应"Not Found"

6.1.2 XMLHttpRequest对象生命周期

由于浏览器的差异性,创建XMLHttpRequest对象时需要使用不同的方法,主要体现在IE浏览器与其他浏览器之间。

由于现在IE已经基本弃用,因此就不会再记录相关知识。

下面是一个标准的XMLHttpRequest创建方法。

(1)创建XMLHttpRequest对象

function createXMLHttp() {var xmlhttp;// code for IE7+, firefox, chrome, opera, safariif (window.XMLHttpRequest) {xmlhttp = new XMLHttpRequest();}// code for IE5, IE6 省略return xmlhttp;
}

(2)建立连接

当XMLHttPRequest对象创建完毕后,便可以通过open()函数建立连接,它指定了请求的url地址以及通过url传递的参数;数据传输方式,默认值为true,表示采用异步传输方式

var xhr = createXMLHttp();
xhr.open('post', '/admin/w/saceUser', true);

(3)发送请求并传递数据

在使用open()函数建立连接后,便可以使用send()函数发送请求,并传递数据content。由于传递的数据并不是必须的,所以content值可以为空

var content = {userName:'kingx', password:'123456'};
xhr.send(content);

(4)处理响应

在XMLHttpRequest对象中有一个很重要的onreadystatechange属性,它表示XMLHttpRequest对象状态改变的事件触发器,每次readyState的取值变化时,属性onreadystatechange对应的函数都会被执行一次。
当readyState的值为4时代表响应接收完成,需要注意的是响应接收完成并不代表请求是成功的,我们需要通过HTTP请求status状态码来判断,当status值为200时代表请求成功。
因此在onreadystatechange()回调函数中,我们需要同时判断readyState和status两个值才能对响应值做正确的处理

xhr.onreadystatechange = function(){// 当readyState为4,且状态码为200时代表请求成功if (xhr.readyState === 4 && xhr.status === 200){// 处理响应值document.write(xhr.responseText);}
}

6.1.3 Ajax的优缺点

(1)优点

  • 可以再不刷新页面的情况下更新数据
  • 异步通信
  • 前后端分离
  • 前后端负载分离
  • 标准化支持

(2)缺点

  • 破坏浏览器的正常后退功能
  • 安全性问题
  • 对搜索引擎支持较弱
  • 违背URL唯一资源定位的初衷

6.2 使用Nodejs搭建简易服务器

这块不过多赘述


6.3 使用Ajax提交form表单

form表单默认提交方式会刷新页面,而且会在页面之间进行跳转。
使用Ajax提交form表单就可以在不刷新页面的情况下提交请求,然后在处理响应时通过JavaScript操作DOM,并展示后台处理的信息。

6.3.1 通用处理

使用Ajax提交form表单时,需要对form表单进行特殊处理,包括:

  • 将form标签的action属性和method属性去掉
  • 将提交form表单按钮的type='submit’改为type=‘btton’

下面是一个例子:

<form name="userForm" id="userForm"> <div class="form-group"><label for="username">用户名</label><input type="text" class="form-control" name="username" id="username"> 		</div><div class="form-group"><label for="password">密码</label><input type="password" class="form-control" name="password" id="password"></div><div class="form-group"><label for="telphone">电话</label><input type="text" class="form-control" name="telphone" id="telphone"> </div><div class="form-group"><label for="email">邮箱</label><input type="text" class="form-control" name="email" id="email"></div><div class="text-center"><input type="button" class="btn btn-default btn-primary" value="提交" id="submit"><input type="button" class="btn btn-default" value="取消" id="cancel"> </div>
</form>

效果如下
在这里插入图片描述

6.3.2 使用原生Ajax进行提交

使用原生Ajax提交form表单包含以下过程:

  • 绑定提交按钮事件
  • 创建XMLHttpRequest对象
  • 建立连接
  • 设置请求头
  • 获取数据
  • 发送请求
  • 处理响应

(1)绑定提交按钮事件

在单击提交按钮时触发Ajax请求的操作,将整个Ajax操作封装在ajaxSubmitForm()函数里。按钮获取与事件绑定使用原生的JS语法。

var submitBtn = document.getElementById('submit');
submitBtn.addEventListener('click',function(){ajaxSubmitForm();
})

(2)创建XMLHttpRequet对象

同样是使用6.1.2小节中封装的函数即可

function createXMLHttp() {var xmlhttp;if (window.XMLHttpRequest){xmlhttp = new XMLHttpRequest();}return xmlhttp;
}var xhr = createXMLHttp();

(3)建立连接

本实例可以理解为一个用户的注册操作,发送的请求为POST秦秋,使用异步处理方式

xhr.open('post', '/saveUser', true);

(4)设置请求头

由于本实例中发送的是POST请求,需要设置数据传输格式,即设置Content-type属性值。可以通过setRequestHeader()函数对其进行设置,将其值设置为比较普遍的 JSON数据格式

xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8');

(5)获取数据

通过原生的DOM操作方式获取页面填写的数据

var username = document.getElementById('username').value; 
var password = document.getElementById('password').value;
var telphone = document.getElementById('telphone').value;
var email = document.getElementById('email').value;
var content = {username: username, password: password, telphone: telphone, email: email
};

因为在请求头中设置了数据传输格式为json,所以需要将content对象处理为json字符串

content = JSON.stringify(content);

(6)发送请求

只需要调用send()函数就可以发送请求

xhr.send(content);

(7)处理响应

设置onreadystatechange属性对应的回调函数,在回调函数中进行判断。当响应接收完毕,readyState为4,同时请求状态码status为200时,即表示请求成功,然后就可以编写对应的处理逻辑


xhr.onreadystatechange = function () {// 当readyStatew为4,且状态码为200时代表请求成功 if (xhr.readyState === 4 && xhr.status === 200) {// 处理响应值document.write(xhr.responseText); }
}

在使用原生Ajax提交form表单内容时,需要考虑浏览器兼容性问题,并且该方式的代码冗余度高,需要经常进行状态的判断,因此这并不是一种很好的处理form表单的方式。

6.3.3 使用jQuery处理Ajax请求进行提交

使用jQuery处理Ajax请求,解决了浏览器兼容性的问题,对原生Ajax请求的高度封装也使得代码变得精简。我们只需要关注在使用Ajax时需要什么,然后传递对应的参数,处理不同的回调即可。

但因为也不用,所以不记录了。

6.3.4 使用jQuery序列化form表单进行提交

表单的序列化,表示的是可以自动将表单内填写的内容自动处理为字符串或者对象格式,便于与服务端进行传递,从而避免重复性地通过代码获取单个表单元素输入值。

同样因为不用,不记录了。

6.3.5 使用FormData对象进行提交

FormData对象是HTML5中新增的对象,服务于Ajax请求,用于发送数据。

FormData对象将数据编译成key-value类型的键值对,以便于XMLHttpRequest对象发送数据。其主要用于发送form表单数据,但也可以独立于form表单,发送带有键的数据。

FormData对象提交的最大的优势是可以异步上传文件。

FormData对象的提交既可以支持原生Ajax请求,也可以支持jQuery请求。jQuery就不记录了。

下面记录一下原生Ajax请求使用FormData对象发送form表单数据:
其他部分,例如XMLHttpRequest对象的创建和请求发送,以及请求成功的回调,这里就不做详细描述,我们重点来看FormData对象的使用

(1)请求头设置
使用原生Ajax请求发送带有文件流的FormData数据时,需要对请求头进行对应的设置,即将Content-type属性设置为application/x-www-form-urlencoded

xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

(2)生成FormData实例

var formData = new FormData();

(3)添加数据
通过append()函数向formData对象中添加需要发送的数据,不管是简单的文本类型数据还是文件类型数据,都可以添加到formData对象中

(4)发送数据
调用send()函数传递FormData对象

xhr.send(formData);

6.4 关于Ajax请求的get方式和post方式

Ajax请求通常会有get和post两种方式

6.4.1 get方式和post方式的区别

使用get和post都可以向服务器发送请求,但是发送机制不同:

  • 参数传递
    • get请求:将参数添加到请求URL的后面,没有请求主体,调用send()函数时传递的参数为null,即xhr.send()
    • post请求:会将请求的数据放在请求体中,用户是无法通过URL直接看到的,调用send()函数时传递的参数为data,即xhr.send(data)
  • 服务端参数获取:使用Express作为服务端框架,get请求通过Request.query来获取参数;而使用 post请求时需要添加中间件,同时通过Request.body来获取参数
  • 传递的数据量:get请求传输的数据量小;post请求传递的数据量大
  • 安全性
    • get请求:安全性较低,因为其请求的参数会出现在URL上,而且采用明文进行数据传输,通过浏览器缓存或者历史记录可以很容易获取到某些隐私请求的参数
    • post请求:安全性较高,post请求通过请求体进行数据传输,数据不会出现在URL上,隐藏了请求数据的信息
  • 处理form表单的差异性

6.4.2 使用get方式和post方式需要注意的点

  • 使用get方式请求时,如果请求的url不发生改变,可能会存在缓存的问题,因此在请求的url后一般会拼接上一个时间戳,以避免出现缓存
  • 使用get方式请求时,请求的参数会拼接在url后,如果浏览器编码、服务器编码、数据库编码格式不一致,可能会导致乱码的问题。通常的做法是对请求的参数经过encodeURIComponent()函数处理
xhr.open('get', '/getUser?username='+encodeURIComponent(username), true)
  • 使用post方式请求时,需要设置请求头中的content-type属性,表示数据在发送至服务器时的编码类型。默认情况下,使用post方式提交form表单时,content-type值为application/x-www-form-unlencoded,另外还可以支持multipart/formdata、application/json等格式
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')

6.4.3 get方式和post方式的使用场景

(1)Ajax使用get方式的场景

  • 请求是为了检索资源,form表单的数据仅用于帮助搜索
  • 传递的数据量小,适合于url中传递参数
  • 数据安全性低,适合明文传输

(2)Ajax使用post方式的场景

  • 请求会修改数据库中的资源,例如增删改
  • 传递的数据量大,超出url中携带参数长度的限制
  • 用于用户名、密码及身份证号等类似敏感信息的数据传输

6.5 Ajax进度事件

在之前的内容里,我们有讲到通过监听readystatechange事件,在回调函数中获取readyState和status的值并判断请求是否成功。在XHR2草案中,增加了Ajax请求进度事件Progress Events规范,使得XMLHttpRequest对象能在请求的不同阶段触发不同类型的事件,所以我们可以不再需要判断readyState的属性,也可以处理请求成功和失败的操作。

在Progress Events规范中增加了 7 个进度事件:

  • loadstart:在开始接收响应时触发
  • progress:在接收响应期间不断触发,直至请求完成
  • error:在请求失败时触发
  • abort:在主动调用abort()函数时触发,表示请求终止
  • load:在数据接收完成时触发
  • loadend:在通信完成或者error、abort、load事件后触发
  • timeout:在请求超时时触发

一个完整的ajax请求都会从loadstart事件开始,然后不间断地触发progress事件,然后触发load、abort、timeout或者error事件的其中一个,最后触发loadend事件。

(1)load事件

只要浏览器接收到了服务器的响应,不管其状态如何都会触发load事件。例如,对于状态码为404的请求,仍然会触发load事件,所以在进行请求成功的处理时,需要判断status的值。一般我们判断status值大于等于200且小于300,或者status值等于304时,都是当作请求成功进行处理。

在loadstart、load等事件的回调函数中,都会接收一个event对象,通过event对象的target属性可以获取到XMLHttpRequest对象的实例,因此可以访问到XMLHttpRequest对象的所有属性和函数

(2)progress事件

progress事件会在浏览器接收数据的过程中周期性调用。progress事件处理程序会接收一个event对象,通过它的target属性同样可以获取到XMLHttpRequest对象的实例,而且在event对象中增加了3个有用的属性,分别是lengthComputable、loaded和total

  • lengthComputable:表示进度信息是否可用。是一个布尔值
  • loaded:表示已经接收到的字节数,它的值是根据Content-Length响应头部确定的预期字节数
  • total:表示响应的实际字节数

通过loaded和total属性值可以计算出接收响应的数据百分比,从而实现进度条


6.6 JSON序列化和反序列化

JSON数据在网络传输时存在两种类型,一种是JSON对象类型,一种是JSON字符串类型。两种类型的转换涉及JSON序列化和反序列化的知识。

6.6.1 JSON序列化

JSON序列化即将JSON对象处理为JSON字符串的过程,以方便数据的传输。

有两种方式实现:

  • 调用JSON对象内置的stringify()函数
  • 为对象仔细定义toJSON()函数

(1)JSON.stringify()函数

JSON.stringify(value[,replacer[,space]])
  • value:待处理成JSON字符串的JavaScript值,通常为对象或者数组
  • replacer:是一个可选参数。如果是一个函数,则表示在序列化过程中,被序列化值的每个属性都会经过该函数处理;如果为一个数组,则表示只有包含在这个数组中的属性名才会被序列化到最终JSON字符串中;如果为null或未传递,则value参数对应值的所有属性都会被序列化
  • space:是一个可选参数,用于指定缩进用的空白字符串,美化输出。如果是数字,则代表对应个数空格,上限为10;如果小于1则没有空格;如果为字符串则取字符串的前10个字符作为空格;如果为null或未传入则没有空格

在JSON序列化时,如果属性值为对象或者数组,则会继续序列化该属性值,直到属性值为基本类型、函数或者Symbol类型才结束。

(2)自定义toJSON()函数

如果一个被序列化的对象拥有toJSON()函数,那么toJSON()函数就会覆盖默认的序列化行为,被序列化的值将不再是原来的属性值,而是toJSON()函数的返回值。

toJSON()函数用于更精确的控制序列化,可以看作是对stringify()函数的补充。

(3)序列化处理的顺序

  • 如果待序列化的对象存在toJSON()函数,则优先调用toJSON()函数,以toJSON()函数的返回值作为待序列化的值,否则返回JSON对象本身
  • 如果stringify()函数提供了第二个参数replacer,则对上一步的返回值经过replacer参数处理
  • 如果stringify()函数提供了第三个参数,则对JSON字符串进行格式化处理,返回最终的结果

6.6.2 JSON反序列化

JSON反序列化即将JSON字符串转换为JSON对象的过程,得到的结果用于在JavaScript中做逻辑处理。

有两种方式实现:

  • 使用JSON对象内置的parse()函数
  • 使用eval()函数

(1)JSON.parse()函数

JSON.parse()函数用来解析JSON字符串,构造由字符串描述的JavaScript值或对象

JSON.parse(text[,reviver])
  • text:带解析的JSON字符串
  • reviver:是可选参数。如果是一个函数,则规定了原始值在返回之前如何被解析改造。如果被解析的JSON字符串是非法的,则会抛出异常
JSON.parse('[1,2,3,true]'); // Array [1, 2, 3, true]
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14} 
JSON.parse('true'); // true
JSON.parse('123.45'); // 123.45

当使用JSON.parse()函数解析JSON字符串时,需要注意两点;

  • JSON字符串中的属性名必须用双引号括起来,否则会解析错误
  • JSON字符串不能以逗号结尾,否则会解析异常

(2)eval()函数

eval()函数用于计算JavaScript字符串,并把它作为脚本来执行。

在使用eval()函数进行JSON反序列化时,其语法如下所示:

eval("(" + str + ")")
  • str:待处理的字符串

因为JSON字符串是以{}开始和结束的,在JavaScript中它会被当作一个语句块来处理,所以必须强制将它处理成一个表达式,所以采用括号

var json1 = '{"name":"kingx"}'; 
var json2 = '{"address":["beijing","shanghai"]}'; 
console.log(eval("(" + json1 + ")"));// {name: "kingx"}
console.log(eval("(" + json2 + ")"));// {address: ["beijing", "shanghai"]}

6.7 Ajax跨域解决方案

6.7.1 浏览器同源策略

浏览器同源策略是浏览器最基本也是最核心的安全功能,它约定客户端脚本在没有明确授权的情况下,不能读写不同源的目标资源。

同源明确地表示为相同协议、域名和端口号,如果两个资源路径在协议、域名、端口号上有任何一点不同,则它们就不属于同源的资源。

在同源策略上,又分为 2 种表现形式:

  • DOM同源策略:禁止对不同页面进行DOM操作,主要的场景是iframe跨域,不同域名下的iframe会限制访问
  • XMLHttpRequest同源策略:禁止使用XMLHttpRequest向不是同源的服务器发送Ajax请求

6.7.2 浏览器跨域限制

主要是由没有遵守浏览器的同源策略引起的,浏览器对跨域访问的限制,可以在很大程度上保护用户的隐私数据安全。

下面是两个实际场景

(1)没有DOM同源策略限制

假如浏览器没有DOM同源策略限制,那么不同域的iframe可以相互访问,黑客就可以采用以下的方式发起攻击:

  • 做一个假网站,里面用iframe嵌套一个银行网站
  • 把iframe宽高调整到占据浏览器可视区的全部空间,这样用户在进入网站后,除了域名,其余看到的内容和其他银行网站是一样的
  • 用户在输入用户名和密码后,主网站就可以跨域访问到所嵌套的银行网站的DOM节点,从而黑客就拿到用户输入的用户名和密码了

(2)没有XMLHttpRequest同源策略限制

假如浏览器没有XMLHttpRequest同源策略限制,那么黑客可以进行跨站请求伪造CSRF攻击,具体方式如下:

  • 用户登录了个人银行页面A,页面A会在Cookie中添加用户信息
  • 用户浏览了恶意页面B,在恶意页面中执行了恶意Ajax请求的代码
  • 此时页面B会向页面A发送Ajax请求,该请求会默认发送用户Cookie信息
  • 页面A会从请求的cookie中提取用户信息,验证用户无误,就会返回用户的隐私数据,而此时数据就会被恶意页面B获取到,从而造成用户隐私数据的泄露
  • 由于Ajax请求的发送会自动执行,所以用户是无感知的

6.7.3 Ajax跨域请求场景

虽然浏览器有跨域访问的限制,但是在某些实际的业务场景中,不可避免地需要进行跨域访问。

6.7.4 CORS

CORS(CrossOrigin Resource Sharing,跨域资源共享)。主要实现方式是服务端通过对响应头的设置,接收跨域请求处理。

不同的服务端框架采用的处理方式不同。

通过服务端的处理不会对前端代码做任何修改,但是由于服务端采用的语言、框架多变,处理方式会依赖各种语言的特性。

6.7.5 JSONP

JSONP是客户端与服务器端跨域通信最常用的解决办法,它的特点是简单适用、兼容老式浏览器、对服务器端影响小。

主要思想可以分 2 步理解:

  • 在网页中动态添加一个script标签,通过script标签向服务器发送请求,在请求中会携带一个请求的callback回调函数名
  • 服务器在接收到请求后,会处理响应获取返回的参数,然后将参数放在callback回调函数中对应的位置,并将callback回调函数通过json格式进行返回

构建JSONP请求实际是创建一个新的script元素,通过src属性指定跨域请求的url,并在url中携带请求成功的回调函数作为参数。

回调函数必须设置为全局函数。因为服务端在响应后会从全局查找回调函数,所以如果回调函数不是定义在全局作用域中,那么会报错。

(1)优点

  • 使用简单,不会有兼容性问题,是目前比较流行的跨域解决方案

(2)缺点

  • 只支持get请求,这是JSONP目前最大的缺点。如果是post请求,那么JSONP则无法完成跨域处理
  • 响应依赖于其他域的实现,如果请求的其他域不安全,可能会对本域造成一定的安全性影响
  • 很难确定JSONP请求是否失败,虽然在HTML5中给script标签增加了onerror事件处理程序,但是存在兼容性问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/108497.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Scikit-Learn中的特征选择和特征提取详解

概要 机器学习在现代技术中扮演着越来越重要的角色。不论是在商业界还是科学领域&#xff0c;机器学习都被广泛地应用。在机器学习的过程中&#xff0c;我们需要从原始数据中提取出有用的特征&#xff0c;以便训练出好的模型。但是&#xff0c;如何选择最佳的特征是一个关键问…

RK3399平台开发系列讲解(存储篇)Linux 存储系统的 I/O 栈

平台内核版本安卓版本RK3399Linux4.4Android7.1🚀返回专栏总目录 文章目录 一、Linux 存储系统全景二、Linux 存储系统的缓存沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 Linux 存储系统的 I/O 原理。 一、Linux 存储系统全景 我们可以把 Linux 存储系…

opencv的haarcascade_frontalface_default.xml等文件

文章目录 GitHub下载在安装好的OpenCV文件夹下寻找opencv-python中获取 GitHub下载 下载地址&#xff1a;https://github.com/opencv/opencv/tree/master/data/haarcascades 在安装好的OpenCV文件夹下寻找 路径如下&#xff1a; 你安装的opencv路径\OpenCV\opencv\build\et…

基于飞腾芯片的设计与调试入门指导

一、啥是自主可控 国产CPU现在厂家细算起来其实有很多,现在华为、小米也在做自己的CPU,瑞芯微、全志等的SoC现在也是广泛应用。但是真正能叫做自主可控的CPU厂商,只有6家。那啥是自主可控?首先来不严谨的讲下现在数字芯片是怎么做的设计。FPGA大家都知道,可以通过Verilog…

Matlab 使用经验分享(常用函数介绍;矩阵常见计算)

Matlab 使用经验分享 大家好&#xff01;最近有很多朋友询问我关于 Matlab 的使用&#xff0c;于是我决定写一篇博客来分享一下我的经验。对于数学和编程爱好者来说&#xff0c;Matlab 是一个非常有用的工具。我自己在数学实验和数学建模竞赛中也经常使用它。那么&#xff0c;…

【JavaEE】面向切面编程AOP是什么-Spring AOP框架的基本使用

【JavaEE】 AOP&#xff08;1&#xff09; 文章目录 【JavaEE】AOP&#xff08;1&#xff09;1. Spring AOP 是什么1.1 AOP 与 Spring AOP1.2 没有AOP的世界是怎样的1.3 AOP是什么 2. Spring AOP 框架的学习2.1 AOP的组成2.1.1 Aspect 切面2.1.2 Pointcut 切点2.1.3 Advice 通知…

【广州华锐互动】VR高校虚拟实验教学平台提供丰富的资源支持,提高教学效果

随着科技的不断进步&#xff0c;虚拟现实(VR)技术已经逐渐渗透到各个领域&#xff0c;其中包括教育。 广州华锐互动利用VR虚拟现实技术打造的VR高校虚拟实验教学平台&#xff0c;是一种新型的教学工具&#xff0c;它提供了一个在线的教学资源管理平台&#xff0c;包含教学平台、…

深度学习在自然语言处理中的十大应用领域

文章目录 1. 机器翻译2. 文本分类3. 命名实体识别4. 问答系统5. 文本生成6. 情感分析7. 语言生成与处理8. 信息检索与摘要9. 文本纠错与修复10. 智能对话系统总结 &#x1f389;欢迎来到AIGC人工智能专栏~深度学习在自然语言处理中的十大应用领域 ☆* o(≧▽≦)o *☆嗨~我是IT陈…

Git企业开发控制理论和实操-从入门到深入(七)|企业级开发模型

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

LAMP介绍与配置

一.LAMP 1.1.LAMP架构的组成 CGI&#xff08;通用网关接口&#xff09;和FastCGI&#xff08;快速公共网关接口&#xff09;都是用于将Web服务器与后端应用程序&#xff08;如PHP、Python等&#xff09;进行交互的协议/接口。 特点 CGI FastCGI 运行方式 每个请求启动…

android外卖点餐界面(期末作业)

效果展示&#xff1a; AndroidMainFest.xml <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"><a…

Hystrix: Dashboard流监控

接上两张服务熔断 开始搭建Dashboard流监控 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocat…

OpenGL —— 2.5、绘制第一个三角形(附源码,glfw+glad)(更新:纹理贴图)

源码效果 C源码 纹理图片 需下载stb_image.h这个解码图片的库&#xff0c;该库只有一个头文件。 具体代码&#xff1a; vertexShader.glsl #version 330 corelayout(location 0) in vec3 aPos; layout(location 1) in vec3 aColor; layout(location 2) in vec2 aUV;out ve…

pnpm安装包管理工具

pnpm安装包管理工具 pnpm代表performant npm&#xff08;高性能的npm&#xff09;&#xff0c;同npm和Yarn&#xff0c;都属于Javascript包管理安装工具&#xff0c;它较npm和Yarn在性能上得到很大提升&#xff0c;被称为快速的&#xff0c;节省磁盘空间的包管理工具。 pnpm…

计算机视觉:深层卷积神经网络的构建

本文重点 上一节课程中我们学习了单卷积层的前向传播,本次课程我们构建一个具有三个卷积层的卷积神经网络,然后从输入(39*39*3)开始进行三次卷积操作,我们来看一下每次卷积的输入和输出维度的变化。 第一层 第一层使用3*3*3的过滤器来提取特征,那么f[1]=3,然后步长s[…

电脑视频编辑软件前十名 电脑视频编辑器怎么剪辑视频

对于大多数创作者而言&#xff0c;视频后期工作基本都是在剪辑软件上进行的。一款适合自己的视频剪辑软件&#xff0c;能够节省出大量的时间和金钱成本&#xff0c;让剪辑师省钱又省心。那么有关电脑视频编辑软件前十名&#xff0c;电脑视频编辑器怎么剪辑视频的相关问题&#…

9.阿里Sentinel哨兵

1.Sentinel Sentinel&#xff08;哨兵&#xff09;是由阿里开源的一款流量控制和熔断降级框架&#xff0c;用于保护分布式系统中的应用免受流量涌入、超载和故障的影响。它可以作为微服务架构中的一部分&#xff0c;用于保护服务不被异常流量冲垮&#xff0c;从而提高系统的稳定…

uview ui 1.x ActonSheet项太多,设置滚动

问题&#xff1a;ActionSheet滚动不了。 使用uview ui &#xff1a;u-action-sheet, 但是item太多&#xff0c;超出屏幕了&#xff0c; 查了一下文档&#xff0c;并没有设置滚动的地方。 官方文档&#xff1a;ActionSheet 操作菜单 | uView - 多平台快速开发的UI框架 - uni-a…

Zebec Protocol:模块化 L3 链 Nautilus Chain,深度拓展流支付体系

过去三十年间&#xff0c;全球金融科技领域已经成熟并迅速增长&#xff0c;主要归功于不同的数字支付媒介的出现。然而&#xff0c;由于交易延迟、高额转账费用等问题愈发突出&#xff0c;更高效、更安全、更易访问的支付系统成为新的刚需。 此前&#xff0c;咨询巨头麦肯锡的一…

机器学习算法示例的收集;MetaAI编码工具Code Llama;“天工AI搜索”首发实测

&#x1f989; AI新闻 &#x1f680; Meta推出新一代AI编码工具Code Llama&#xff0c;助力程序员提高开发效率 摘要&#xff1a;Meta推出Code Llama&#xff0c;这是一个基于Llama 2语言模型打造的AI编码工具&#xff0c;能够生成新的代码并调试人类编写的工作。Code Llama可…