javascript Ajax 学习
前言:这是笔者学习之后自己的理解与整理。如果有错误或者疑问的地方,请大家指正,我会持续更新!
AJAX是asynchronousjavascript and XML的简写,就是异步的javascript和XML。这一技术能够向服务器请求额外的数据而无须刷新整个页面,会带来更好的用户体验。虽然名字中包含XML,但是ajax通信与数据格式无关。
创建对象
因为XMLHTTPRequest()是一个构造函数,所以需要实例化一个XMLHttpRequset对象。下面是创建XHR对象的兼容写法;
如果要建立多个不同的请求,就要实例化多个不同的XMLHttpRequset对象;
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
发送请求
要想把请求发送到服务器,我们就需要使用open()方法和send()方法。
open()
open()方法需要三个参数:xhr.open("GET","test.json",true);
第一个参数定义发送请求所使用的方法(GET还是POST),不区分大小写,但通常使用大写字母,记得带引号。
GET用于常规请求,它适用于当URL完全指定请求资源,当请求对服务器没有任何副作用以及当服务器的响应是可缓存的情况下。
然而,在以下情况中,请使用POST请求:
- 无法使用缓存文件(更新服务器上的文件或数据库)
- 向服务器发送大量数据(
POST没有数据量限制) - 发送包含未知字符的用户输入时,
POST比GET更稳定也更可靠
第二个参数规定服务器端脚本的URL(该文件可以是任何类型的文件,比如.txt和.xml,或者服务器脚本文件,比如.asp和.php(在传回响应之前,能够在服务器上执行任务)。
第三个参数规定是否异步发送请求的布尔值,如果不填写,默认为true,表示异步发送。如果接受的是同步响应,则需要将open()方法的第三个参数设置为false,那么send()方法将阻塞直到请求完成。客户端javascript是单线程的,当send()方法阻塞时,它通常会导致整个浏览器界面冻结。如果连接的服务器响应慢,那么用户的浏览器将冻结,所以应该避免使用同步。
send()
send()方法接收一个参数,即要作为请求主体发送的数据。调用send()方法后,请求被分派到服务器。
如果是GET方法,send()方法无参数,或参数为null;如果是POST方法,send()方法的参数为要发送的数据。
xhr.open("GET","test.json",false);
xhr.send(null);
GET
GET用于常规请求,它适用于当URL完全指定请求资源,当请求对服务器没有任何副作用以及当服务器的响应是可缓存的情况下。
【数据发送】
使用GET方式发送请求时,数据被追加到open()方法中URL的末尾,可以直接看到,存在安全隐患。
数据以问号开始,名和值之间用等号链接,名值对之间用和号&分隔。使用GET方式发送的数据常常被称为查询字符串。
【编码】
由于URL无法识别特殊字符,所以如果数据中包含特殊字符(如中文),则需要进行编码,编码的方式有很多种,其中encodeURIComponent()函数可把字符串作为URI组件进行编码。该方法主要对;/?:@&=+$,#等这些用于分隔URI组件的字符以及中文进行编码。由于此方法对:/都进行了编码,所以不能用它来对网址进行编码,而适合对URI中的参数进行编码
在GET请求中,为了避免缓存的影响,可以向URL末尾添加一个随机数或时间戳。
var url = 'test.php' +'?name=' + encodeURIComponent("你好");
xhr.open('GET',url+'&'+Number(new Date()),true);
xhr.send(null);
POST
POST请求通常用于向服务器发送应该被保存的数据。
POST方法常用于HTML表单。它在请求主体中包含额外数据且这些数据常存储到服务器上的数据库中。
在open()方法第一个参数的位置传入POST,就可以初始化一个POST请求。
【设置请求头】
默认情况下,服务器对POST请求和提交表单的请求并不会一视同仁。因此,服务器端必须有程序来读取发送过来的原始数据,并从中解析出有用的部分。不过,可以使用XHR来模仿表单提交:首先将content-Type头部信息设置为application/x-www-form-urlencoded,也就是表单提交时的内容类型;
使用setRequestHeader()方法可以设置自定义的请求头部信息。这个方法接受两个参数:头部字段的名称头部字段的值。要成功发送请求头部信息,必须在调用open()方法之后且调用send()方法之前调用setRequestHeader()方法。
在项目中,又是需要验证用户登录,可以设置请求头验证。机制就是:在用户首次登录成功之后,服务器发送token到客户端,客户端存入cookie。用户做任何请求操作时,在ajax的请求头里带上token,用以server-end做登录状态验证。
【发送主体】
发送POST请求的第三步就是向send()方法中传入某些数据,这一点和GET请求不一样。由于XHR最初的设计主要是为了处理XML,因此可以在此传入XML DOM文档,传入的文档经序列化之后将作为请求主体被提交到服务器。当然,也可以在此传入任何想发送到服务器的字符串。
接下来要以适当的格式创建一个字符串,并使用send()方法发送。
POST数据的格式与GET数据的格式相同,名和值之间用等号链接,名值对之间用和号&分隔。
【编码】
由于使用POST方式传递数据时,需要设置请求头"content-type",这一步骤已经能够自动对特殊字符(如中文)进行编码,所以就不再需要使用encodeURIComponent()方法了。
POST请求主要用于数据提交,相同URL的重复POST请求从服务器得到的响应可能不同,所以不应该缓存使用POST方法的请求。
GET对所发送信息的数量有限制,一般在2000个字符。与GET请求相比,POST请求消耗的资源会更多一些。从性能角度来看,以发送相同的数据计,GET请求的速度最多可POST请求的两倍。
xhr.open('POST',url,true);
//设置请求头
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
//拼接数据
var strData = 'name="abc"&num=123';
//发送请求
xhr.send(strData);
接收响应
一个完整的HTTP响应由状态码、响应头集合和响应主体组成。
在收到响应后,这些都可以通过XMLHttpRequset对象的属性和方法使用,主要有以下4个属性:
responseText作为响应主体被返回的文本(文本格式)responseXML如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存着响应数据的XML - DOM文档(document格式)statusHTTP状态码(数字形式)statusTextHTTP状态说明(文本格式)
在接收到响应后,第一步是检查status属性,以确定响应已经成功返回。一般来说,可以将HTTP状态码为200作为响应成功的标志。此时,responseText属性的内容已经就绪,而且在内容类型正确的情况下,responseXML也可以访问了。此外,状态码为304表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本;当然,也意味着响应是有效的。
无论内容类型是什么,响应主体的内容都会保存到responseText属性中,而对于非XML数据而言,responseXML属性的值将为null;
if((xhr.status >=200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
}else{
alert('请求失败,响应代码为:' + xhr.status);
}
异步响应和同步响应
如果不设置open()方法的第三个参数(默认为true,即异步响应)。
如果接收的是异步响应,这就需要检测XMLHttpRequset对象的readyState属性,该属性表示请求/响应过程的当前活动阶段。这个属性可取的值如下:0(UNSENT) 未初始化 还没调用open()
| 状态码 | 状态 | 描述 |
|---|---|---|
| 1 | (OPEND) 启动 | 已经调用open() ,但还没调用 send() |
| 2 | (HEADERS_RECEIVED) 发送 | 己经调用 send() 方法,且接收到头信息。 |
| 3 | (LOADING) 正在接收 | 已经接收到部分响应主体信息。 |
| 4 | (DONE) 完成 | 已经接收到全部响应数据,而且已经可以在客户端使用了。 |
理论上,只要readyState属性值由一个值变成另一个值,都会触发一次readystatechange事件。可以利用这个事件来检测每次状态变化后readyState的值。通常,我们对readyState值为4的阶段感兴趣,因为这时所有数据都已就绪。
必须在调用open()之前指定onreadystatechange事件处理程序才能确保跨浏览器兼容性,否则将无法接收readyState属性为0和1的情况。
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status == 200){
alert(xhr.responseText);
}
}
}
如果将open()方法的第三个参数设置为false,接收的就是同步响应,那么send()方法将阻塞直到请求完成。一旦send()返回,仅需要检查XHR对象的status和responseText属性即可。
应该避免使用同步请求。客户端javascript是单线程的,当send()方法阻塞时,它通常会导致整个浏览器UI冻结。如果连接的服务器响应慢,那么用户的浏览器将冻结,用户体验非常不好。
进度事件
一般地,使用readystatechange事件探测HTTP请求的完成。XHR2规范草案定义了进度事件Progress Events规范,XMLHttpRequest对象在请求的不同阶段触发不同类型的事件,所以它不再需要检査readyState属性。
有以下6个进度事件:
loadstart: 在接收到响应数据的第一个字节时触发progress: 在接收响应期间持续不断地触error: 在请求发生错误时触发abort: 在因为调用abort()方法而终止连接时触发load: 在接收到完整的响应数据时触发loadend: 在通信完成或者触发error、abort或load事件后触发timeout: 超时发生时触发
每个请求都从触发loadstart事件开始,接下来,通常每隔50毫秒左右触发一次progress事件,然后触发load、error、abort或timeout事件中的一个,最后以触发loadend事件结束
对于任何具体请求,浏览器将只会触发load、abort、timeout和error事件中的一个。XHR2规范草案指出一旦这些事件中的一个发生后,浏览器应该触发loadend事件。
load
响应接收完毕后将触发load事件,因此也就没有必要去检查readyState属性了。但一个完成的请求不一定是成功的请求,例如,onload事件的处理程序应该检查XMLHttpRequest对象的status状态码来确定收到的是“200OK”而不是“404 Not Found”的HTTP响应
progress
progress事件会在浏览器接收新数据期间周期性地触发。而onprogress事件处理程序会接收到一个event对象,其target属性是XHR对象,但包含着三个额外的属性:lengthComputable、loaded 和 total。其中,lengthComputable是一个表示进度信息是否可用的布尔值,loaded表示已经接收的字节数,total表示根据Content-Length响应头部确定的预期字节数。有了这些信息,就可以为用户创建一个进度指示器了。
upload上传进度
除了为监控HTTP响应的加载定义的这些有用的事件外,XHR2也给出了用于监控HTTP请求上传的事件。在实现这些特性的浏览器中,XMLHttpRequest对象将有upload属性。upload属性值是一个对象,它定义了addEventListener()方法和整个progress事件集合,比如onprogress和onload。但upload对象没有定义onreadystatechange属性,upload仅能触发新的事件类型。
<input type="file" name="file1" id="file1" style="display:none">
<button id="btn">上传文件</button>
<div id="pro"></div>
<div id="result"></div>
<script>
btn.onclick = function(){
file1.click();
pro.innerHTML = result.innerHTML = '';
}
file1.onchange = function(){
//创建xhr对象
var xhr = new XMLHttpRequest();
var data = file1.files[0];
//上传事件
xhr.upload.onprogress = function(e){
e = e || event;
if (e.lengthComputable){
pro.innerHTML = "上传进度为:" + e.loaded + " of " + e.total + " bytes" + ';百分比为:' + e.loaded/e.total;
}
}
xhr.onload = function(e){
var data = xhr.responseText;
e = e || event;
if(xhr.status == 200){
result.innerHTML = data;
}
};
//发送请求
xhr.open('post','pp.php',true);
xhr.setRequestHeader("content-type",data.type);
xhr.send(data);
}
</script>
超时、中止、错误事件
HTTP请求无法完成有3种情况。如果请求超时,会触发timeout事件。如果请求中止,会触发abort事件。最后,像太多重定向这样的网络错误会阻止请求完成,但这些情况发生时会触发error事件。
可以通过调用XMLHttpRequest对象的abort()方法来取消正在进行的HTTP请求。调用abort()的主要原因是完成取消或超时请求消耗的时间太长或当响应变得无关时。
XHR对象的timeout属性等于一个整数,表示多少毫秒后,如果请求仍然没有得到结果,就会自动终止。该属性默认等于0,表示没有时间限制。如果请求超时,将触发ontimeout事件。
var xhr = new XMLHttpRequest();
btn.onclick = function(){
xhr.abort();
}
xhr.onabort = function(){
console.log("请求已终止");
}
xhr.ontimeout = function(){
console.log('请求超时');
}
xhr.timeout = 3000;
xhr.onerror = function(){
console.log("请求报错");
}
xhr.onloadend = function(){
console.log("请求结束");
}
封装
ajax({
url: "./TestXHR.aspx", //请求地址
type: "POST", //请求方式
data: {
name: "super",
age: 20
}, //请求参数
dataType: "json",
success: function (response, xml) {
// 此处放成功后执行的代码
},
fail: function (status) {
// 此处放失败后执行的代码
}
});
function ajax(options) {
options = options || {};
options.type = (options.type || "GET").toUpperCase();
options.dataType = options.dataType || "json";
var params = formatParams(options.data);
//创建 - 非IE6 - 第一步
if (window.XMLHttpRequest) {
var xhr = new XMLHttpRequest();
} else { //IE6及其以下版本浏览器
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//接收 - 第三步
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
var status = xhr.status;
if (status >= 200 && status < 300) {
options.success && options.success(xhr.responseText, xhr.responseXML);
} else {
options.fail && options.fail(status);
}
}
}
//连接 和 发送 - 第二步
if (options.type == "GET") {
xhr.open("GET", options.url + "?" + params, true);
xhr.send(null);
} else if (options.type == "POST") {
xhr.open("POST", options.url, true);
//设置表单提交时的内容类型
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(params);
}
}
//格式化参数
function formatParams(data) {
var arr = [];
for (var name in data) {
arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name]));
}
arr.push(("v=" + Math.random()).replace(".", ""));
return arr.join("&");
}
javascript Ajax 学习的更多相关文章
- Ajax学习心得
Ajax学习心得 大致学了下Ajax,才知道它不是某种编程语言,而是一种在无需加载整个页面的情况下能够更新部分网页的技术.了解了它的功能后觉得这真是一种好的技术,这得给前端和运维省多少力啊! 传统的网 ...
- AJax 学习笔记二(onreadystatechange的作用)
AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...
- 大量Javascript/JQuery学习教程电子书合集
[推荐分享]大量Javascript/JQuery学习教程电子书合集,送给有需要的人 不收藏是你的错^_^. 经证实,均可免费下载. 资源名称 资源大小 15天学会jQuery(完整版).pd ...
- [推荐分享]大量Javascript/JQuery学习教程电子书合集,送给有需要的人
不收藏是你的错^_^. 经证实,均可免费下载. 资源名称 资源大小 15天学会jQuery(完整版).pdf 274.79 KB 21天学通JavaScript(第2版)-顾宁燕扫描版.pdf ...
- AJAX学习前奏----JS基础加强
AJAX学习前奏----JS基础加强 知识概要: 1.js类&属性&方法的定义 2.静态属性与方法 3.构造方法 4.原型的使用 5.Object对象直接加属性和方法 6.JSO ...
- JavaScript紧凑学习
JavaScript紧凑学习 windows本地,调用命令行: win键+R 键入cmd , (cmd是Command 命令行 简称) 目录是C盘下的 C:\Users\Administrator&g ...
- AJAX学习2
作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正. 本文学习内容:https://www. ...
- [学习笔记]AJAX学习
AJAX学习 ——在w3cschool学习AJAX的学习笔记 参考网站:w3cschool XMLHttpRequest 是 AJAX 的基础. XMLHttpRequest 对象 所有现代浏览器均支 ...
- javascript立体学习指南
javascript立体学习指南第一章:首先了解javascript 首先,什么是javascript? JavaStrip出生于1995年,是一种文本脚本语言,成都装修公司是一种动态的.弱类型的.基 ...
随机推荐
- Kettle建立数据库链接报错-'MS SQL Server' driver (jar file) is installed. kettle的bug,对于12.2而言
1.链接sql server数据库报错 错误连接数据库 [My_vm_win_sql] : org.pentaho.di.core.exception.KettleDatabaseException: ...
- GIS地理处理工具案例教程-成本距离
GIS地理处理工具案例教程-成本距离 关键词:最短路径,成本路径,最佳路径,最优路径,路径分析,选线分析 商务合作,科技咨询,版权转让:向日葵,135-4855__4328,xiexiaokui#qq ...
- Flutter -------- 新手 WanAndroid 项目练习
一个简单Flutter项目wanandroid,先前用Kotlin来开发过,适合新手练习. 用到的库 包含功能: http+数据解析 网络请求数据列表展示 Banner轮播 WebView跳转详情 D ...
- jsoup爬取某网站安全数据
jsoup爬取某网站安全数据 package com.vfsd.net; import java.io.IOException; import java.sql.SQLException; impor ...
- OpenBLAS编译 Debug x64 Win10 vs2015
OpenBLAS编译 Debug x64 Win10 vs2015 >------ 已启动生成: 项目: ZERO_CHECK, 配置: Debug x64 ------ > Che ...
- Flutter中的Stack、Align、Positioned的使用
import 'package:flutter/material.dart'; import 'package:flutter_testdemo001/res/listData.dart'; void ...
- ros 学习 array 的添加
array的添加,使用 arry[i]赋值时会出现段错误,需要使用array.push_back添加到数据中,在ros中array数组是以vector方式存储的. 例如: 包含数组的msg定义为: h ...
- RabbitMQ 入门教程(PHP版) 简单Demo
RabbitMQ的关键字说明 (1)Broker:经纪人.提供一种传输服务,维护一条从生产者到消费者的传输线路,保证消息数据能按照指定的方式传输.粗略的可以将图中的RabbitMQ Server当作B ...
- Spring Boot应用的打包和部署
传统的Web应用在发布之前通常会打成WAR包,然后将WAR包部署到Tomcat等容器中使用,而通过前面的学习我们已经知道,Spring Boot应用既能以JAR包的形式部署,又能以WAR包的形式部署. ...
- 【 Linux 】Systemd 配置文件说明及编写(2)
1. 开机启动 对于支持 systemd 的软件,如果想要设置开机启动,就执行如下命令(以 http 为例): systemctl enable httpd 上面的命令相当于在 /etc/system ...