这几天利用下班时间好好研究了下promise,以后得开发应该会常常用到promise。
通俗得理解promise就是处理异步,处理回调地狱而存在,让你能随心所欲得控制代码得执行顺序。
我目前用到得场景有多文件上传,利用promise去排列好请求,一个一个得发起请求,以保证上传得顺序;多个请求同时发送,待他们全部成功后执行一些操作,等等。
我们通过问题来探寻promise
什么是promise
promise本身是在使用微队列(微队列和宏队列是异步得两种队列,微队列优先级高于宏队列),依靠函数得同步和异步,把回调函数统一按顺序处理;
promise得构成
这里写了一个最简单的promise,方便对应理解
new Promise((resolve,reject)=>{
console.log("1")
resolve()//
})
//第一个微队列块
.then(()=>{
console.log("6")
})
.then(()=>{
console.log("6")
})
promise内部一共有3个状态(其实是4个状态,知道3个就够我们学习和了解):pending(进行中),resolved(成功),rejected(失败);pending会单向变成resolved或者rejected,当状态确认后就会执行回调函数也就是then()中传入得回调函数;
promise中得执行器(excutor)(同步):传入需要进行封装的函数,这个执行器必须包括resolve,reject两个参数,这两个参数就是两个函数,这两个函数就是改变promise内部得状态,如果不传入且执行这两个函数其中一个,promise将永远是pending状态
new Promise(excutor)
promise得回调函数(then)(异步):then就是promise得回调函数,就是当我们执行器得状态确认后执行得回调函数,then接受两个函数:onResolved,onRejected;这两个参数是成功或者失败得回调函数,且then之后会返回一个promise,这也就是为什么promise能够链式调用
这就是promise的构成,剩下的catch,all,race是在原来的基础上进行封装,我们后面再谈。
promise的用处
把一些回调函数展平,本来多个请求依赖上一个请求,我们第一时间想到得是回调,但是多了后代码变得难以阅读,可以用promise来展平方便阅读;同时promise本身是一个异步操作,也可以用来进行封装一些组件(虽然可以直接利用settimeout这一类宏队列)
promise语法糖async,await
这里写了一个demo方便理解
function fn2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('fn2');
resolve(2)
}, 2000);
})
}
function fn3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('fn3');
resolve(3)
}, 1000);
})
}
async function fn() {
console.log(fn2);
const p2 = await fn2()
const p3 = await fn3()
console.log(p2, p3);
}
fn()
这两个语法糖,
async后面跟一个函数,他会将这个函数封一层promise,这个函数的返回值(不抛错误就是resolved,抛了错误就是rejected)就决定是resolved还是rejected。
await后面接受一个表达式,常常是一个Promise(放一个表达式,一个同步函数没任何意义,还是立即执行),注意await只能接受成功的promise,如果错误会报错让你抓异常,所以需要手动try catch
promise的一些别的接口
promise实例接口:
then()//之前已经讲过
catch()//then的变形可以理解为then(undefind,onRejected)
promise本身的方法:
Promise.resolve()直接返回一个成功的promise
Promise.rejected()直接返回一个失败的promise
Promise.all(arr)//参数是一个promise数组,当他们都成功时返回一个结果数组,起顺序和promise数组顺序一致
Promise.race(arr)//参数时一个promise数组,返回第一个完成的promise的结果