js-Promise
简介
Promise
一、概念
1.概念
Promise是es6提供的一个构造函数,es6+进行了完善,是一种新的异步处理方式,使用的时候需要new一个Promise对象,用来表示异步操作的结果
2.原理
打印一下,console.log(Promise)打印出来是native,无法看到实现代码。
通过console.dir(Promise)可以打印出来,console.dir意思是对一个对象进行检查,会打印出一些细节。如下图,在Promise构造函数中有all,allSettled,any,race,resolve,reject等方法,在原型prototype中有then,catch,finally等方法。
二、为什么使用Promise
1.Promise优点
异步操作的代码规范
回调地狱
可以批量处理异步任务,统一处理抛出的错误
2.Promise缺点
一旦新建就会立即执行,无法中途取消
当pendding时无法知道Promise处于哪个状态,是刚刚开始还是快要结束
如果不设置回调函数,内部错误无法反应到外部
三、使用
1.参数
接收一个回调函数作为参数,这个回调函数会立即执行,它属于同步任务,它又接收两个回调函数作为参数,resolve和reject,这两个函数是内部实现的,成功调用resolve,将Promise状态从pendding变为fulfilled,失败调用reject,将状态从pendding变为rejected
Promise对象有三种状态,pendding,fulfilled,rejected;只有结果才能决定进入哪个状态,一旦状态改变就不会在变;只有两种可能,p到f和p到r
链式调用,then/catch/finally方法都会返回一个新的promise对象
2.原型方法
then:
resolve接收不同类型的参数表现不同,如下三种情况
接收常规类型,then回调中就能拿到常规类型;
1 | let p = new Promise((res, rej) => { |
接收promise,那外promise的状态由接收的promise的状态决定;
1 | let o = new Promise((res, rej) => { |
接收thenable对象,会调用thenable对象的then方法,而不执行then回调里的语句
1 | let tobj = { |
catch:reject接收任意类型的参数,接收什么就输出什么。如果reject的参数是一个promise的话,就影响catch的捕获异常。
catch的捕获规则是是由外向内
的(就远原则
),在依次执行代码的时候,如果遇到异常,就直捕获停止,不会向下再去捕获。
finally: finally 方法是不接收参数的,无论是fulfilled还是rejected,finally都会执行
3.类方法
Promise.resolve(),相当于new Promise((resolve, reject) => {resolve()})
Promise.reject(), 同上
Promise.all:批量处理异步任务,接收一个promise数组,将多个Promise包裹成一个新的Promise,新的Promise的状态由包裹的Promise的状态共同决定,
只要有一个失败的就进catch,成功的那些结果也拿不到
1 | // 模拟Promise.all |
Promise.race:谁先执行完就输出谁的结果
Promise.allSettled:在所有promise有结果后进then,这个promise的结果一定是成功的,一定会进then
Promise.any:只要有一个成功,就会进入then,如果都失败,才会进catch
1 | eg: |
四、使用场景
根据其概念分析,处理异步任务时都可以使用promise包裹,通过链式调用来代替回调函数。
1.下个操作依赖上个异步操作的结果,这时候在之前就会用回调函数,现在可以用promise
2.一个页面,有多个请求,我们需求所有的请求都返回数据后再一起处理渲染,all可以统一处理抛出的错误,如上例中使用promise.all处理批量下载请求
3.大量数据在一个then 里面处理 显得臃肿,多个渲染数据分别给个then,让其各司其职
4.promise.race可以做超时提示,接收两个异步任务,一个请求,一个定时器,谁先结束用谁的结果
5.axios本身就是基于promise的一种封装,上例中jszip的generateAsync方法也是返回了一个promise