1.接口调用方式
原生ajax
基于jQuery的ajax
fetch
axios
异步
JavaScript的执行环境是「单线程」
所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这
个任务执行完后才能执行下一个,它会「阻塞」其他任务。这个任务可称为主线程
异步模式可以一起执行多个任务
JS中常见的异步调用
定时任务
ajax
事件函数
传统的ajax
$.ajax({ url:'http://localhost:2000', success:function(data){ console.log(data) } }) $.ajax({ url:'http://localhost:2000/data', success:function(data){ setTimeout(function(){console.log(data)},300) } }); $.ajax({ url:'http://localhost:2000/data2', success:function(data){ console.log(data) } })
获取的结果
可以看到 打印出来的数据并不是我们获取的顺序 要想打印的数据是我们获取的顺序 就要嵌套起来 如下:
// 要想是我们请求的顺序返回结果 就必须要嵌套起来 如果很多 代码风格就很难看也难以修改 像18层地狱一样 // 所以 这种代码风格被称为 回调地狱 $.ajax({ url:'http://localhost:2000', success:function(data){ console.log(data) $.ajax({ url:'http://localhost:2000/data', success:function(data){ console.log(data) $.ajax({ url:'http://localhost:2000/data2', success:function(data){ console.log(data) } }) } }); } })
打印结果
要想是我们请求的顺序返回结果 就必须要嵌套起来 如果很多 代码风格就很难看也难以修改 像18层地狱一样 所以 这种代码风格被称为 回调地狱
ajax处理异步的问题
之前处理异步是通过纯粹的回调函数的形式进行处理
很容易进入到回调地狱中,剥夺了函数return的能力
问题可以解决,但是难以读懂,维护困难
稍有不慎就会踏入回调地狱 - 嵌套层次深,不好维护
所以就用到了 我今天要讲的promise
promise讲解
用途
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列
promise是一个对象 首先我们打印一下promise 看看他的属性和方法
console.dir(Promise); //console.dir()可以显示一个对象所有的属性和方法
红圈就是我们需要重点掌握了解的 下面会来一一介绍
Promise基本使用
我们使用new来构建一个Promise Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject, 分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数. .then获取结果 第一个函数获取正确的结果 第二个获取出错是的结果
var p = new Promise(function(resolve, reject){ // 这里用于实现异步任务 setTimeout(function(){ var flag = false; if(flag) { // 正常情况 resolve('hello'); }else{ // 异常情况 reject('出错了'); } }, 100); }); p.then(function(data){ console.log(data) },function(info){ console.log(info) });
基于promise 发送ajax请求
<script type="text/javascript"> /* 基于Promise发送Ajax请求 */ function queryData(url) { var p = new Promise(function(resolve, reject){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState != 4) return; if(xhr.readyState == 4 && xhr.status == 200) { // 处理正常的情况 resolve(xhr.responseText); }else{ // 处理异常情况 reject('服务器错误'); } }; xhr.open('get', url); xhr.send(null); }); return p; } //发送一个ajax请求 // queryData('http://localhost:3000/data') // .then(function(data){ // console.log(data); // },function(info){ // console.log(info) // }); // ============================ // 发送多个ajax请求并且保证顺序 queryData('http://localhost:3000/data') .then(function(data){ console.log(data) return queryData('http://localhost:3000/data1'); }) .then(function(data){ console.log(data); return queryData('http://localhost:3000/data2'); }) .then(function(data){ console.log(data) }); </script>
.then 参数中的函数返回值
1.返回promise实例对象
返回的1该实例对象会调用下一个then
2.返回的是普通值
会直接传递给下一个then,通过then参数中的函数接收该值。
<script type="text/javascript"> /* then参数中的函数返回值 */ function queryData(url) { return new Promise(function(resolve, reject){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState != 4) return; if(xhr.readyState == 4 && xhr.status == 200) { // 处理正常的情况 resolve(xhr.responseText); }else{ // 处理异常情况 reject('服务器错误'); } }; xhr.open('get', url); xhr.send(null); }); } queryData('http://localhost:3000/data') .then(function(data){ return queryData('http://localhost:3000/data1'); }) .then(function(data){ return new Promise(function(resolve, reject){ setTimeout(function(){ resolve(123); },1000) }); }) .then(function(data){ return 'hello'; }) .then(function(data){ console.log(data) }) 返回的是 hello </script>
实例方法
.then()
得到异步任务正确的结果
.catch()
获取异常信息
.fifinally()
成功与否都会执行(不是正式标准)
<script type="text/javascript"> /* Promise常用API-实例方法 */ // console.dir(Promise); function foo() { return new Promise(function(resolve, reject){ setTimeout(function(){ // resolve(123); reject('error'); }, 100); }) } // foo() // .then(function(data){ // console.log(data) // }) // .catch(function(data){ // console.log(data) // }) // .finally(function(){ // console.log('finished') // }); // -------------------------- // 两种写法是等效的 foo() .then(function(data){ console.log(data) },function(data){ console.log(data) }) .finally(function(){ console.log('finished') }); </script>
静态(对象)方法
.all()
Promise.all 方法接受一个数组作参数,数组中的对象(p1、p2、p3)均为promise实例(如果不是一个
promise,该项会被用 Promise.resolve 转换为一个promise)。它的状态由这三个promise实例决定
.race()
Promise.race 方法同样接受一个数组作参数。当p1, p2, p3中有一个实例的状态发生改变(变为 fulfilled
或 rejected ),p的状态就跟着改变。并把第一个改变状态的promise的返回值,传给p的回调函数
<script type="text/javascript"> /* Promise常用API-对象方法 */ // console.dir(Promise) function queryData(url) { return new Promise(function(resolve, reject){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState != 4) return; if(xhr.readyState == 4 && xhr.status == 200) { // 处理正常的情况 resolve(xhr.responseText); }else{ // 处理异常情况 reject('服务器错误'); } }; xhr.open('get', url); xhr.send(null); }); } var p1 = queryData('http://localhost:3000/a1'); var p2 = queryData('http://localhost:3000/a2'); var p3 = queryData('http://localhost:3000/a3'); // Promise.all([p1,p2,p3]).then(function(result){ // console.log(result) // })
// all 中的参数 [p1,p2,p3] 和 返回的结果一 一对应["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"] // 由于p1执行较快,Promise的then()将获得结果'P1'。p2,p3仍在继续执行,但执行结果将被丢弃。
Promise.race([p1,p2,p3]).then(function(result){ console.log(result) }) </script>
axios
介绍
基于promise用于浏览器和node.js的http客户端
支持浏览器和node.js
支持promise
能拦截请求和响应
自动转换JSON数据
能转换请求和响应数据
axios基础用法
1.get和 delete请求传递参数
通过传统的url 以 ? 的形式传递参数
restful 形式传递参数
通过params 形式传递参数
2.post 和 put 请求传递参数
通过选项传递参数
通过 URLSearchParams 传递参数
# 1. 发送get 请求 axios.get('http://localhost:3000/adata').then(function(ret){ # 拿到 ret 是一个对象 所有的对象都存在 ret 的data 属性里面 // 注意data属性是固定的用法,用于获取后台的实际数据 // console.log(ret.data) console.log(ret) }) # 2. get 请求传递参数 # 2.1 通过传统的url 以 ? 的形式传递参数 axios.get('http://localhost:3000/axios?id=123').then(function(ret){ console.log(ret.data) }) # 2.2 restful 形式传递参数 axios.get('http://localhost:3000/axios/123').then(function(ret){ console.log(ret.data) }) # 2.3 通过params 形式传递参数 axios.get('http://localhost:3000/axios', { params: { id: 789 } }).then(function(ret){ console.log(ret.data) }) #3 axios delete 请求传参 传参的形式和 get 请求一样 axios.delete('http://localhost:3000/axios', { params: { id: 111 } }).then(function(ret){ console.log(ret.data) }) # 4 axios 的 post 请求 # 4.1 通过选项传递参数 axios.post('http://localhost:3000/axios', { uname: 'lisi', pwd: 123 }).then(function(ret){ console.log(ret.data) }) # 4.2 通过 URLSearchParams 传递参数 var params = new URLSearchParams(); params.append('uname', 'zhangsan'); params.append('pwd', '111'); axios.post('http://localhost:3000/axios', params).then(function(ret){ console.log(ret.data) }) #5 axios put 请求传参 和 post 请求一样 axios.put('http://localhost:3000/axios/123', { uname: 'lisi', pwd: 123
axios 全局配置
# 配置公共的请求头 axios.defaults.baseURL = 'https://api.example.com'; # 配置 超时时间 axios.defaults.timeout = 2500; # 配置公共的请求头 axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; # 配置公共的 post 的 Content-Type axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios 拦截器
请求拦截器
请求拦截器的作用是在请求发送前进行一些操作
例如在每个请求体里加上token,统一做了处理如果以后要改也非常容易
响应拦截器
响应拦截器的作用是在接收到响应后进行一些操作
例如在服务器返回登录状态失效,需要重新登录的时候,跳转到登录页
# 1. 请求拦截器 axios.interceptors.request.use(function(config) { console.log(config.url) # 1.1 任何请求都会经过这一步 在发送请求之前做些什么 config.headers.mytoken = 'nihao'; # 1.2 这里一定要return 否则配置不成功 return config; }, function(err){ #1.3 对请求错误做点什么 console.log(err) }) #2. 响应拦截器 axios.interceptors.response.use(function(res) { #2.1 在接收响应做些什么 var data = res.data; return data; }, function(err){ #2.2 对响应错误做点什么 console.log(err) })