ajax入门
ajax入门
dleeiAjax
什么是ajax?
AJAX 代表异步的 JavaScript 和 XML(Asynchronous JavaScript And XML)。简单点说,就是使用 XMLHttpRequest
对象与服务器通信。它可以使用 JSON、XML、HTML 和文本文件等格式发送和接收数据。AJAX 最吸引人的就是它的“异步”特性,也就是说它可以在不重新刷新页面的情况下与服务器通信,交换数据,或更新页面
简单来说
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
AJAX 不需要任何浏览器插件,但需要用户允许 JavaScript 在浏览器上执行
XMLHttpRequest 只是实现 Ajax 的一种方式
AJAX 不是新的编程语言,而是一种使用现有标准的新方法
是⼀个 默认异步执⾏机制的功能,AJAX分为同步(async = false)和异步(async = true)
什么是同步请求?(false)
同步请求是指当前发出请求后,浏览器什么都不能做,
必须得等到请求完成返回数据之后,才会执行后续的代码,
相当于生活中的排队,必须等待前一个人完成自己的事物,后一个人才能接着办。
也就是说,当JS代码加载到当前AJAX的时候会把页面里所有的代码停止加载,页面处于一个假死状态,
当这个AJAX执行完毕后才会继续运行其他代码页面解除假死状态
什么是异步请求?(默认:true)
默认异步:异步请求就当发出请求的同时,浏览器可以继续做任何事,
Ajax发送请求并不会影响页面的加载与用户的操作,相当于是在两条线上,各走各的,互不影响。
一般默认值为true,异步。异步请求可以完全不影响用户的体验效果,
无论请求的时间长或者短,用户都在专心的操作页面的其他内容,并不会有等待的感觉。
ajax的使用
ajax实现的基本步骤
- 创建XMLHttpRequest对象,即创建一个异步调用对象.
- 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
- 设置响应HTTP请求状态变化的函数.
- 发送HTTP请求.
- 获取异步调用返回的数据.
- 使用JavaScript和DOM实现局部刷新.
1、创建XMLHttpRequest
对象
1 | var xmlHttpRequest = new XMLHttpRequest(); |
2、创建HTTP请求
创建了XMLHttpRequest
对象之后,必须为XMLHttpRequest
对象创建HTTP请求,用于说明XMLHttpRequest
对象要从哪里获取数据。通常可以是网站中的数据,也可以是本地中其他文件中的数据。
open()
语法
创建HTTP请求可以使用XMLHttpRequest
对象的open
()方法,其语法代码如下所示:
1 | XMLHttpRequest.open(method,URL,flag,name,password); |
method | 指定HTTP的请求方法,常用的方法为get 和post |
---|---|
URL | HTTP请求的URL地址 |
flag | 指定是否使用异步方式。true表示异步、false表示同步,默认为true(可选) |
name | 用于输入用户名。如果服务器需要验证,则必须使用该参数(可选) |
password | 用于输入密码。若服务器需要验证,则必须使用该参数(可选) |
send()
方法
通过
XMLHttpRequest
对象的send()
方法,将客户端页面的数据发送给服务端语法:
1
xhr.send([body]) //body: 在 XHR 请求中要发送的数据体,如果不传递数据则为 null
如果使用
GET
请求发送数据的时候,需要注意如下:- 将请求数据添加到
open()
方法中的url
地址中 - 发送请求数据中的
send()
方法中参数设置为null
- 将请求数据添加到
配置链接信息
3、设置响应HTTP请求状态变化的函数
创建完HTTP请求之后,应该就可以将HTTP请求发送给Web服务器了。然而,发送HTTP请求的目的是为了接收从服务器中返回的数据。从创建XMLHttpRequest对象开始,到发送数据、接收数据、XMLHttpRequest对象一共会经历以下5中状态。
1 | readyState === 0 : 表示未初始化完成,也就是 open 方法还没有执行 |
一个最基本的 ajax 请求就是上面三步 但是光有上面的三个步骤,我们确实能把请求发送到服务端
如果服务端正常的话,响应也能回到客户端 但是我们拿不到响应
如果想要拿到响应,我们需要有两个前提条件
- 本次 HTTP 请求是成功的,也就是我们下面要说的 http 状态码为 200 ~ 299
- ajax 对象也有自己的状态码,用来表示本次 ajax 请求中各个阶段
在通过Ajax的异步调用获得服务器端数据之后,可以使用JavaScript或DOM来将网页中的数据进行局部更新。
axios
axios是什么?
[Axios](axios中文文档|axios中文网 | axios (axios-js.com)) 是一个基于 promise 网络请求库,作用于node.js
和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http
模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
本质上就是对XMLHttpRequest()对象的封装
axios的基本使用
1.引入axios.js文件
2.使用axios( )函数
1 | axios({ |
url
统一资源定位符(英语:Uniform Resource Locator,缩写:URL,或称统一资源定位器、定位地址、URL地址[1])俗称网页地址,简称网址,是因特网上标准的资源的地址(Address),如同在网络上的门牌。它最初是由蒂姆·伯纳斯-李发明用来作为万维网的地址,现在它已经被万维网联盟编制为因特网标准RFC 1738。
url组成
以“https://zh.wikipedia.org:443/w/index.php?title=随机页面”为例,其中:
- https,是协议;
- zh.wikipedia.org,是服务器;
- 443,是服务器上的网络端口号;
- /w/index.php,是路径;
- ?title=Special:随机页面,是查询参数。
aixos查询参数
参数就是和后台交互的时候给他的一些信息
get请求
axios的params方法会把接收到的参数以字符串的形式拼接到请求地址的后面
1 | axios({ |
这样服务端就能接受到两个参数 一个是 a,值是 100,一个是 b,值是 200
post 请求
post 请求的参数是携带在请求体中的,所以不需要在url 后面拼接
1 | axios({ |
- 但是携带参数
get
和post
两个方式还是有区别的
GET 还是 POST?
与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。
然而,在以下情况中,请使用 POST 请求:
- 不愿使用缓存文件(更新服务器上的文件或数据库)
- 向服务器发送大量数据(POST 没有数据量限制)
- 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
常用请求方法
get(默认请求) | 获取数据 |
---|---|
post | 数据提交 |
put | 修改数据(全部) |
delete | 删除数据 |
patch | 修改数据(部分) |
axios错误处理
语法:在then( )方法的后面调用.catch( )方法捕获错误,传入回调函数并定义形参
1 | axios({ |
http 请求报文
http的请求报文由四个部分组成
1.请求行
2.请求头
3.请求空行
4.请求体
请求行
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔
请求头
请求头由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
User-Agent:产生请求的浏览器类型。
Accept:客户端可识别的内容类型列表。
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机
请求空行
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
请求体
请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。
响应报文
概念:服务器按照http协议要求的格式,返回给浏览器的内容
和请求报文也是一样也是有四个部分组成
1.响应行(状态行):协议、HTTP 响应状态码、状态信息
2.响应头:以键值对的格式携带的附加信息,比如:Content-Type
3.响应空行:分隔响应头,空行之后的是服务器返回的资源
4.响应体:返回的资源
http响应码
状态码 | 说明 |
---|---|
1xx | 消息响应 |
2xx | 成功响应 |
3xx | 重定向 |
4xx | 客户端错误 |
5xx | 服务端错误 |
常见http响应码
200———请求成功
301——— 资源(网页等)被永久转移到其它URL
404———请求的资源(网页等)不存在
500———内部服务器错误,无法完成请求
表单信息收集插件
form-serialize
1 | const data = serialize(form, { hash: true, empty: true }) |
参数1: 表单元素对象
参数2: 配置对象
hash: true 将收集到的数据封装成对象, false 将收集到的数据封装成查询字符串
empty: 如果用户没有输入指定的内容, 也获取
一般不用管他全部默认设置为true,后面好方便操作
深入axios实现原理
xhr使用步骤
创建xhr对象
1
const xhr = new XMLHttpRequest()
调用open方法,设置url和请求方法
1
xhr.open('GET', 'http://hmajax.itheima.net/api/province')
监听loadend事件,接受结果,
会在调用xhr.send方法发送请求后,不管成功与否都会执行loadend事件里面的回调函数
1 | xhr.addEventListener('loadend', () => { |
调用send方法,向服务器发起请求
1
xhr.send()
get请求
URLSearchParams
转换查询参数使用步骤:
创建
URLSearchParams
对象1
2
3
4const params = new URLSearchParams({
参数名1:参数值1,
参数名2:参数值2,
})生成至指定格式的查询参数
1
const queryString = paramsObj.toString(params)
post请求
请求头设置 Contnet -Type:application/json
1 | xhr.setRequestHeader('Content-Type', 'application/json') |
发送请求携带json字符串数据
1 | xhr.send(JSON.stringify(obj)) |
promise
概念:**Promise
** 对象表示异步操作最终的完成(或失败)以及其结果值
这是引用MDN上面的概念,十分的晦涩难懂,简单来说,所谓Promise
,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息
promise基本使用
Promise对象是一个构造函数,用来生成promise实例
下面的代码是一个最基本简单的Promise实例对象
1 | // 1. 创建 Promise 对象 |
Promise对象接收一个函数作为参数: 回调函数, 该函数会立即执行
里面的回调函数有两个参数:(由 JavaScript 引擎提供,不用自己部署)
参数1: resolve 函数,将Promise 表示从发送请求时的pending状态变为resolve,会在异步操作成功时调用,并将结果作为参数传递出去
参数2: reject 函数, 将Promise 表示从发送请求时的pending状态变为reject,会在异步操作失败时调用,并将结果作为参数传递出去
Promise实例对象还有一个then方法和catch方法他是定义在原型对象身上的
then方法
在回调函数内执行 resolve 就会把结果带到这里
下面是一个小例子:
1 | function runAsync(){ |
在runAsync()的返回上直接调用then方法,then接收一个参数,是函数,并且会拿到我们在runAsync中调用resolve时传的的参数。运行这段代码,会在2秒后输出“执行完成”,紧接着输出“随便什么数据”。
then里面的函数就跟我们平时的回调函数一个意思,能够在runAsync这个异步任务执行完成之后被执行。这就是Promise的作用了,简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。
then链式调用
1 | function runAsync1(){ |
1 | runAsync1() |
在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了
1 | runAsync1() |
一个任务(即一个 Promise
对象)可以被多次使用 .then()
方法进行链式调用。
在 Promise
链中,每次调用 .then()
方法都会返回一个新的 Promise
对象,这个新的 Promise
对象会在上一个 Promise
成功并返回数据时被解析
catch方法
在回调函数内执行 reject就会把结果带到这里
1 | function getNumber(){ |
getNumber函数用来异步获取一个数字,2秒后执行完成,如果数字小于等于5,我们认为是“成功”了,调用resolve修改Promise的状态。否则我们认为是“失败”了,调用reject并传递一个参数,作为失败的原因。
运行getNumber并且在then中传了两个参数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。所以我们能够分别拿到他们传过来的数据。
多次运行我们只会得到两种结果,要么是小于5,要么是大于5,失败了
这时候就会用到catch方法了
1 | getNumber() |
效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中
1 | getNumber() |
在resolve的回调中,我们console.log(somedata);而somedata这个变量是没有被定义的。如果我们不用Promise,代码运行到这里就直接在控制台报错了,不往下运行了
all方法
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调
1 | Promise |
用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。所以上面代码的输出结果就是:
race的用法
all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法,这个词本来就是赛跑的意思。race的用法与all一样
假如我们的异步任务1延时1秒后执行,异步任务2和3都是延时2秒后执行
1 | Promise |
这三个异步操作同样是并行执行的。结果你应该可以猜到,1秒后runAsync1已经执行完了,此时then里面的就执行了
在then里面的回调开始执行时,runAsync2()和runAsync3()并没有停止,仍旧再执行。于是再过1秒后,才会输出
这个race有什么用呢?使用场景还是很多的,比如我们可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作,
1 | //请求某个图片资源 |
requestImg函数会异步请求一张图片,我把地址写为”xxxxxx”,所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息