Promise对象是ES6引入的异步编程解决方案,它有3种状态pending(进行中)、fulfilled(已成功)和 rejected(已失败)它的执行顺序是这样的pending=>fulfilled|rejected ,也可以理解为它返回成功和失败2种状态。下面用一个简单的例子来实现一个异步操作。
Let a= new Promise(function(resolve,reject){ let b=1; setTimeout(()=>{ if (b===1){ resolve("我成功了") }else{ resolve("是失败了") } },100) }) a.then(res=>{ //.then方法返回成功时的示例 console.log(res) }).catch(err=>{ //.catch方法返回失败的示例 console.log(err) })
上面的代码看到没,针对异步操作,我们可以像使用变量一样,在我们想要的位置直接使用异步返回的值。如果上述代码不使用es6的Promise那使用回调函数
let a= (c)=>{ let b=1 setTimeout(()=>{ if (b===1){ c.success("成功") }else{ c.err("失败") } },100) } a({ success:(res)=>{ console.log(res,1) }, err:(err)=>{ console.log(err,1) } })
和明显Promise还是更简洁的,也更直关和易读
Promise的语法
new Promise(function(resolve,reject){})
其中resolve是成功后需要返回的数据,reject失败后需要返回的数据。需要new就证明这是一个构造函数,通过console.dir(a)我们可以看到它的所有方法如下图
有1个构造函数Constructoro里面就有resolve,reject。另外有3个方法.then(成功).catch(失败).finally(成功失败都执行),上上面已经讲过了就不讲了,下面是其他方法的说明
constructoro里的all函数既Promise.all
Promise.all是把多个Promise对象合并成一个数组并返回,示例代码
let a=Promise.all([ new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve("数组1") },100) }), new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve("数组2") },100) }), new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve("数组3") },100) }), ] ) a.then(res=>{ console.log(res) })
打印后返回['数组1', '数组2', '数组3']。Promise.all里只要有一个实例不管是主动执行reject还是出错,那么都将抛出错误。.then获取不到任何数据!
constructoro里的race函数既Promise.race
race是按照异步的先后顺序的返回数据的,即使该实例执行的是reject。打个比方,我们有5个人进行50米跑步,那么谁第一名就返回它的数据,我们看示例
let a=Promise.race([ new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve("数组1") },300) }), new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve("数组2") },200) }), new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve("数组3") },100) }) ] ) a.then(res=>{ console.log(res) }).catch(err=>{ console.log(err) })
控制台显示的是数据3,因为它的时间是最短的。
constructoro里的any函数既Promise.any
这个函数的机制是这样的,只要有一个实例成功了,那么就返回数据,除非是全部失败,那么将返回一个失败的信息。它返回的对象也是按照先手顺序执行的,大家可以把上面Promise.race的示例代码改成Promise.any,然后把实例都执行reject,最后再打印会发现.catch返回AggregateError: All promises were rejected,如果resolve那么数组3将被返回。
constructoro里的allSettled函数既Promise.allSettled
我们首先上一个实例
Promise.allSettled([ Promise.resolve("ok"), Promise.reject("err") ]).then(res=>{ console.log(res) })
很明显,allSettled不管是resolve还是reject都通过.then返回一个object数据,通过数据里的status属性来确定返回成功还是失败。那么在Promise.all里,我们很难确定所有的实例请求是否结束,那么用allSettled就很容易判断了。
最后的总结
虽然异步编程可以使用回调函数,但很显然使用Promise让逻辑更清晰,功能也更强大。上述文章只是介绍了Promise基本用法,如果完全掌握一般来说也就够用了。当然Promise还有链式调用,事件循环,宏任务,微任务等,Promise还有自身的语法糖Async和Await等等其他相关知识。为什么别人说js入门简单,精通难。这简单的一个小功能就有很多的知识点,真的要完全掌握也是需要点时间的