1.异步函数
有哪些呢 : setTimeout setInnterval ajax axios
同步:执行完上一个任务,再执行下一个任务
异步:多个事件并发执行,比如医院挂号的时候在玩手机,玩手机不会影响挂号
异步函数的执行:由于是异步的,不会阻塞主线程代码的执行
2.回调函数
把一个函数当做参数传递,将来指定的时机调用,这个函数就是回调函数,一般异步操作,都会用到回调函数
//回调地狱 setTimeout(function(){ setTimeout(function(){ setTimeout(function(){ },1000) },1000) },1000)
回调函数存在的问题:
-
阅读性不好,回调函数不会立马执行
-
回调函数有大量的嵌套,可维护性差
-
嵌套过多,层层嵌套,造成回调地狱
promise就是为了解决回调地狱的问题
3.promise使用
1.首先创建new promise对象,promise是构造函数,里面有一个回调函数,有两个参数,resolve,reject,promise内部写的就是异步代码,一般封装一个异步操作。
resolve,reject,是promise内部提供的两个函数,异步成功 执行reslove,失败调用 执行reject。
2.使用promise
p.then( ) 有then方法,是resolve,然后.catch 里面是失败执行的,axios请求就是异步,
// 先创建promise对象 const p=new Promise((resolve,reject)=>{ setTimeout(function(){ resolve() },0) }) console.log(p) //此时是pending p.then(res=>{ console.log('请求成功') }) .catch(err=>{ console.log("err") })
4.promise三种状态
pending 等待状态 --- 进行中--默认状态
fulfilled 成功状态 --- 已完成 - 调用 了resolve函数,promise的状态就会标记为成功
rejected 失败状态 ----调用 了reject函数,promise的状态就会标记为失败
如果只有p什么都不执行,就是promisestate就是pending。
pending-------->fulfilled
pending-------->rejected
一旦promise的状态发送变化,状态就不会在变化,状态就凝固了,不会由成功变成失败
5.使用promise解决回调地狱--优化代码
模拟异步
异步请求会拿到结果,把结果作为参数,res就是then的结果,res就是响应回来的结果,如果执行resolve调用的是.then方法,失败调用的是catch方法
function fn(){ return new Promise((resolve,reject)=>{ setTimeout(function(){ resolve('第一次') },1000) }) } fn().then((res)=>{ console.log(res) return fn() }) .then(res=>{ console.log(res,0) }) .catch(err=>{ console.log(err) })
把一次次的请求封装在函数里,然后return p ,得到一个promise对象,然后fn调用就是得到的promise对象,若再次调用,得到又一个promise。
若有多个pomise需要处理,支持链式编程
链式编程:如果上一个.then中返回了一个新的promise对象,就可以交给下一个.then继续处理,如果在promise的链式操作中发生了错误,就可以使用.catch方法进行捕获和处理
.then后面直接跟又一个.then即可。res不受影响,此时如果把resolve改成reject,那么就会输出错误,不会执行下面的then。
每一次调用函数,都会返回一个新的promise对象
一堆.then就解决了回调,promise执行了异步,但是写法是同步的,是上一个执行完再去执行下一个。
6.promise的常用静态方法
在构造函数上直接定义的方法就是静态方法
1.promise.all
等待机制 promise.all([promise1,promise2,...........])
发起并行的promise异步操作,会等待所有的异步操作都完成后,每一个promise都完成,才会走.then
fn1和fn2都执行完,才会执行.then,会以数组形式转回复fn1的结果。fn2的结果。指的是都成功执行,比如fn2是reject,就会报错。
此时在.all里写一个catch,那么就会输出刚刚reject里的内容。
function fn1(){ return new Promise((resolve,reject)=>{ setTimeout(function(){ // resolve(1) reject("hello") },20) }) } function fn2(){ return new Promise((resolve,reject)=>{ setTimeout(function(){ resolve(2) }) }) } Promise.all([fn1(),fn2()]) .then(res=>{ console.log(res) //[1, 2] }) .catch(err=>{ console.log(err) //hello })
2.promise.race
赛跑机制 mise.all([promise1,promise2,...........])
发起并行的promise异步操作,只要任何一个异步操作完成后,就会走.then,如果把时间变一下,执行快的那个,不管对错,都先执行快的。
function fn1(){ return new Promise((resolve,reject)=>{ setTimeout(function(){ // resolve(1) reject("hello111") },40) }) } function fn2(){ return new Promise((resolve,reject)=>{ setTimeout(function(){ resolve(2) },20) }) } Promise.race([fn1(),fn2()]) .then(res=>{ console.log(res) //2 }) .catch(err=>{ console.log(err) })
7.axios理解
axios支持promise对象,axios返回的是promise对象。
var proObj=axios({ url:"http://www.liulongbin.top:3009/api/news" }) console.log(proObj) //Promise {<pending>}
在函数内部,直接return axios,也是得到一个promise对象
以上写法复杂,所以采用async和await
async和await
1.定义
async和await 是promise的简写
async是用于修饰一个函数,表示一个函数是异步的,async和await必须一起使用,如果async函数内没有await,async是没有意义的,就会变成全是同步的,只有遇到了await,往下,才是异步的内容。
await要写在async函数中
await后面会跟一个promise对象,await会阻塞async函数的执行,直到等到promise执行成功的结果,即resolve的结果
await只会等待promise成功的结果,如果失败了会报错,需要try..catch
2.用法
在function前加async,await后面跟的肯定得是promise对象,执行了2以后,遇到await,就等待promise执行完,得到返回值res-即异步执行的结果,然后输出1和res,因为遇到await就会暂停。
那么就不需要.then来获取得到结果,直接res=await的结果,就能得到结果,如果需要多个的话,那么就再赋值一个res1,可以再写一个异步函数fn1,在setTimeout里写一个异步resolve,