一、前言:为什么会出现Promise? Promise的重要性我认为没有必要多讲,概括起来说就是五个字:必!须!得!掌!握! 。
而且还要掌握透彻,在实际的使用中,有非常多的应用场景我们不能立即知道应该如何继续往下执行。
最常见的一个场景就是ajax请求,通俗来说,由于网速的不同,可能你得到返回值的时间也是不同的,
这个时候我们就需要等待,结果出来了之后才知道怎么样继续下去。
1 2 3 4 5 6 7 8 9 10 let xhr = new XMLHttpRequest ();xhr.open ('get' , 'https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=82294778&appsecret=4PKVFula&city=%E5%8C%97%E4%BA%AC' ); xhr.send (); xhr.onreadystatechange = function ( ) { if (xhr.readyState === 4 ) { if (xhr.status >= 200 && xhr.status < 300 ) { console .log (xhr.responseText ) } } }
在ajax的原生实现中,利用了onreadystatechange事件,当该事件触发并且符合一定条件时,才能拿到想要的数
据,之后才能开始处理数据,这样做看上去并没有什么麻烦,但如果这个时候,我们还需要另外一个ajax请求,这
个新ajax请求的其中一个参数,得从上一个ajax请求中获取,这个时候我们就不得不等待上一个接口请求完成之
后,再请求后一个接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 let xhr = new XMLHttpRequest ();xhr.open ('get' , 'https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=82294778&appsecret=4PKVFula&city=%E5%8C%97%E4%BA%AC' ); xhr.send (); xhr.onreadystatechange = function ( ) { if (xhr.readyState === 4 ) { if (xhr.status >= 200 && xhr.status < 300 ) { console .log (xhr.responseText ) let xhr = new XMLHttpRequest (); xhr.open ('get' ,'http://www.xx.com?a' +xhr.responseText ); xhr.send (); xhr.onreadystatechange = function ( ){ if (xhr.readyState === 4 ){ if (xhr.status >=200 && xhr.status <300 ){ console .log (xhr.responseText ) } } } } } }
当出现第三个ajax(甚至更多)仍然依赖上一个请求时,我们的代码就变成了一场灾难。
这场灾难,往往也被称为回调地狱 。
因此我们需要一个叫做Promise的东西,来解决这个问题,当然,除了回调地狱之外,还有个非常重要的需求就是
为了代码更加具有可读性和可维护性,我们需要将数据请求与数据处理明确的区分开来 。
上面的写法,是完全没有区分开,当数据变得复杂时,也许我们自己都无法轻松维护自己的代码了。
这也是模块化过程中,必须要掌握的一个重要技能,请一定重视。
二、Promise是什么?
Promise是异步编程的一种解决方案,比传统的解决方案回调函数更合理、更强大。
ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。
指定回调函数的方式也变得更加灵活易懂,也解决了异步回调地狱
的问题
旧方案是单纯使用回调函数,常见的异步操作有:定时器、fs模块、ajax、数据库操作
从语法上说,Promise是一个构造函数;
从功能上说,Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值。
2.1 Promise的初体验 创建promise对象(pending状态)
const p = new Promise(executor);
其中:
executor函数: 执行器 (resolve, reject) => {}
resolve函数: 内部定义成功时我们调用的函数 value => {}
reject函数: 内部定义失败时我们调用的函数 reason => {}
executor会在Promise内部立即同步调用,异步操作在执行器中执行
实例对象调用Promise原型中的then方法来完成对结果的处理
1 2 3 4 5 6 7 8 9 10 11 12 <script> const p = new Promise ((resolve, reject ) => { resolve ('ok' ); }) console .log (p) p.then (() => { console .log ('发奖金' ) }, () => { console .log ('不发奖金' ) }) </script>
三、使用Promise的好处? 3.1 指定回调函数的方式更加灵活
旧的:必须在启动异步任务前指定
promise:启动异步任务->返回promise对象->给promise对象绑定回调函数
(甚至可以在异步任务结束后指定/多个)
3.2 可以解决回调地狱问题,支持链式调用
什么是回调地狱?
回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
回调地狱的缺点?
不便于阅读
不便于异常处理
解决方案?
promise链式调用
终极解决方案?
async/await
四、Promise实例对象的两个属性
五、resolve函数以及reject函数
resolve:修改promise对象的状态,由pending修改到fulfilled;将实参设置到这个属性PromiseResult中。
reject:修改promise对象的状态,由pending修改到rejected;将实参设置到这个属性PromiseResult中。
案例1:利用promise来进行读取文件操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 const fs = require ('fs' );const p = new Promise ((resolve, reject ) => { fs.readFile (__dirname + '/data.txt' , (err, data ) => { if (err) { reject (err); }else { resolve (data); } }) }); p.then (value => { console .log (value.toString ()); },reason => { console .log (reason); })
案例2:利用promise进行ajax请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <body> <button > 发送ajax请求</button > <script > let btn = document .querySelector ('button' ); btn.onclick = function ( ){ const p = new Promise ((resolve,reject )=> { const xhr = new XMLHttpRequest (); xhr.open ('get' ,'https://www.yiketianqi.com/free/day?appid=82294778&appsecret=4PKVFula&unescape=1' ); xhr.send (); xhr.onreadystatechange = function ( ){ if (xhr.readyState == 4 ){ if (xhr.status == 200 ){ resolve (xhr.responseText ); }else { reject (xhr.response ); } } } }); p.then (value => { console .log (JSON .parse (value)); },reason => { console .log ('获取信息失败' ); }) } </script > </body>
案例3:利用promise进行数据库操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 const mongoose = require ('mongoose' );new Promise ((resolve, reject ) => { mongoose.connect ('mongodb://127.0.0.1/project' ); mongoose.connection .on ('open' , ()=> { resolve (); }); mongoose.connection .on ('error' , () => { reject (); }) }).then (value => { const NoteSchema = new mongoose.Schema ({ title : String , content : String }) const NoteModel = mongoose.model ('notes' , NoteSchema ); NoteModel .find ().then (value => { console .log (value); }, reason => { console .log (reason); }) }, reason => { console .log ('连接失败' ); })
案例4:封装一个函数,作用是读取文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const fs = require ('fs' );function ReadFileFun (path ){ return new Promise ((resolve,reject )=> { fs.readFile (path,(err,data )=> { if (err){ reject (err) }else { resolve (data); } }) }); } ReadFileFun ('./data.txt' ).then (value => { console .log (value.toString ()); },reason => { console .log (reason); })
node中的promisify
promisify (只能在 NodeJS 环境中使用)
promisify 是 util 模块中的一个方法 util 是 nodeJS 的内置模块
作用: 返回一个新的函数, 函数的是 promise 风格的.
1 2 3 4 5 6 7 8 9 10 11 const util = require ('util' );const fs = require ('fs' );const mineReadFile = util.promisify (fs.readFile );mineReadFile ('./resource/2.html' ).then (value => { console .log (value.toString ()); }, reason => { console .log (reason); })
六、Promise对象的状态 Promise对象通过自身的状态来控制异步操作,Promise实例具有三种状态.
异步操作未完成:pending
异步操作成功:fulfilled
异步操作失败:rejected
这三种的状态的变化途径只有两种
从pending(未完成)到fulfilled(成功)
从pending(未成功)到rejected(失败)
一旦状态发生变化,就凝固了,不会再有新的状态变化,这也是Promise这个名字的由来,它的英语意思”承诺”,
一旦承诺生效,就不得再改变了,这也意味着Promise实例的状态变化只可能发生一次。
在Promise对象的构造函数中,将一个函数作为第一个参数。而这个函数,就是用来处理Promise的状态变化。
上面的resolve和reject都为一个函数,他们的作用分别是将状态修改为resolved和rejected。
因此,Promise的最终结果只有两种。
1 2 异步操作成功,Promise 实例传回一个值(value),状态变为fulfilled. 异步操作失败,Promise 实例抛出一个错误(error),状态变为rejected
七、Promise的then方法 then:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的promise对象
成功的状态:执行第一个回调函数
失败的状态:执行第二个回调函数
promise.then()返回的新promise的结果状态由什么决定?
(1) 简单表达: 由then()指定的回调函数执行的结果决定
(2) 详细表达:
① 如果抛出异常, 新promise变为rejected, reason为抛出的异常
1 2 3 4 5 6 7 8 9 10 11 const p = new Promise ((resolve,reject )=> { resolve ('ok' ); }); let result = p.then (value => { throw '错误' ; },reason => { console .log (reason); }); console .log (result);
② 如果返回的是非promise的任意值, 新promise变为fulfilled, PromiseResult为返回的值
1 2 3 4 5 6 7 8 9 10 11 const p = new Promise ((resolve,reject )=> { resolve ('ok' ); }); let result = p.then (value => { return 100 ; },reason => { console .log (reason); }); console .log (result);
③ 如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const p = new Promise ((resolve,reject )=> { resolve ('ok' ); }); let result = p.then (value => { return new Promise ((resolve,reject )=> { reject ('error' ); }) },reason => { console .log (reason); }); console .log (result);
八、Promise的链式调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 const p = new Promise ((resolve,reject )=> { reject ('error' ); }); p.then (value => { console .log (value); },reason => { console .log (reason); }).then (value => { console .log (value); },reason => { console .log (reason); })
案例:通过promise的链式调用来读取文件
回调地狱的方式:
1 2 3 4 5 6 7 8 9 10 11 const fs = require ('fs' );fs.readFile ('./resource/1.html' ,(err,data1 )=> { if (err) throw err; fs.readFile ('./resource/1.html' ,(err,data2 )=> { if (err) throw err; fs.readFile ('./resource/1.html' ,(err,data3 )=> { if (err) throw err; console .log (data1 + data2 + data3); }) }) })
Promise的形式:
需求:读取resource下三个文件内容,并在控制台合并输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 new Promise ((resolve,reject )=> { fs.readFile ('./resource/1.html' ,(err,data )=> { if (err) reject (err); resolve (data); }) }).then (value => { return new Promise ((resolve,reject )=> { fs.readFile ('./resource/2.html' ,(err,data )=> { if (err) reject (err); resolve ([value,data]); }) }) }).then (value => { return new Promise ((resolve,reject )=> { fs.readFile ('./resource/3.html' ,(err,data )=> { if (err) reject (err); value.push (data); resolve (value); }) }) }).then (value => { console .log (value.join ("" )); })
九、Promise下的几种方法 9.1 Promise.resolve() 将一个普通值转化为promise类型的数据
若参数为非promise对象,则返回的结果为成功状态的promise对象
1 2 3 4 let p1 = Promise .resolve (123 );console .log (p1);let p2 = Promise .resolve (undefined );console .log (p2);
若参数为promise对象,参数的状态决定返回结果的状态
1 2 3 4 5 6 7 let p3 = Promise .resolve (new Promise ((resolve,reject )=> { resolve ('success' ); })); console .log (p3);let p4 = Promise .resolve (Promise .resolve (Promise .resolve ("OK" )));console .log (p4);
9.2 Promise.reject() 返回的结果始终为失败的Promise对象
1 2 console .log (Promise .reject (123 ));console .log (Promise .reject (Promise .resolve ('ok' )));
9.3 Promise.catch() 功能是用来指定失败的回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 let p = new Promise ((resolve,reject )=> { reject ('error' ); }); p.catch (reason => { console .log (reason); }); p.then (value => { console .log (value); }).then (value => { console .log (value); }).catch (reason => { console .log (reason); })
9.4 Promise.all() 作用:针对于多个Promise的异步任务进行处理
接收的参数:promise数组
返回值:promise对象,状态由promise数组中的对象状态
决定
若每个对象状态都为
成功,则返回的promise对象状态为成功,
成功的结果值为每个promise对象成功结构值组成的数组
若其中一个对象
状态为失败,则返回的promise对象状态为失败,
失败的结果值为失败的promise对象的结果值
1 2 3 4 5 6 7 let p1 = new Promise ((resolve, reject ) => { resolve ('ok' ); }) let p2 = Promise .resolve ('hello' );let p3 = Promise .resolve ('oh yeah' );let result = Promise .all ([p1, p2, p3])console .log (result);
当有一个ajax请求,它的参数需要另外2个甚至更多请求都有返回结果之后才能确定,
那么这个时候,就需要用到Promise.all来帮助我们应对这个场景。
Promise.all接收一个Promise对象组成的数组作为参数,
当这个数组所有的Promise对象状态都变成resolved或者rejected的时候,它才会去调用then方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 let p1 = new Promise ((resolve,reject )=> { resolve ('成功01' ); }) let p2 = new Promise ((resolve,reject )=> { resolve ('成功02' ); }).catch (reason =>console .log (reason)); let p3 = new Promise ((resolve,reject )=> { resolve ('成功03' ); }) let pAll = Promise .all ([p1,p2,p3]);console .log (pAll)pAll.then (value => { console .log (value); },reason => { console .log (reason); })
案例1:模拟请求三个接口中的数据,全部请求成功后获取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 function getUsersList ( ) { return new Promise ((resolve, reject ) => { setTimeout (() => { resolve ('用户列表的数据' ); }, 1000 ); }) } function getBannersList ( ) { return new Promise ((resolve, reject ) => { setTimeout (() => { resolve ('轮播图的数据' ); }, 2000 ); }) } function getVideoList ( ) { return new Promise ((resolve, reject ) => { setTimeout (() => { resolve ('视频列表的数据' ); }, 3000 ); }) } function initLoad ( ) { let all = Promise .all ([getUsersList (), getBannersList (), getVideoList ()]); all.then (value => { console .log (value); }) } initLoad ();
案例2:修改多文件读取代码
1 2 3 4 5 6 7 8 9 10 11 12 const fs = require ('fs' );const util = require ('util' );const mywriteFile = util.promisify (fs.readFile );let one = mywriteFile ('./resource/1.html' );let two = mywriteFile ('./resource/2.html' );let three = mywriteFile ('./resource/3.html' );let result = Promise .all ([one,two,three]);result.then (value => { console .log (value.join ('' )); },reason => { console .log (reason); })
9.5 Promise.race() Promise.race race 赛跑的意思
参数: promise 数组
返回结果: promise 对象
状态由『最先改变状态的 promise对象』决定
结果值由 『最先改变状态的 promise对象』决定
1 2 3 4 5 6 7 8 9 let p1 = new Promise ((resolve, reject ) => { setTimeout (() => { resolve ('ok' ); }, 2000 ) }); let p2 = Promise .resolve ('success' );let p3 = Promise .resolve ('oh hou' );let result = Promise .race ([p1, p2, p3]);console .log (result);
与Promise.all相似的是,Promise.race都是以一个Promise对象组成的数组作为参数。
不同的是,只要当数组中的其中一个Promsie状态变成resolved或者rejected时,就可以调用.then方法了。
而传递给then方法的值也会有所不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <script> let p1 = new Promise ((resolve, rejct ) => { setTimeout (() => { resolve ('p1成功' ) }, 2000 ); }) let p2 = new Promise ((resolve, rejct ) => { setTimeout (() => { resolve ('p2成功' ); }, 1000 ); }, 1000 ); const prace = Promise .race ([p1, p2]); </script>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function request ( ) { return new Promise ((resolve, reject ) => { setTimeout (() => { resolve ('请求成功' ); }, 4000 ); }) } function timeout ( ) { return new Promise ((resolve, reject ) => { setTimeout (() => { reject ('网络不畅,请求超时' ); }, 3000 ); }); } Promise .race ([request (), timeout ()]).then (value => { console .log (value) }).catch (reason => { console .log (reason) })
9.6 Promise.allSettled() Promise.allSettled()方法,用来确定要一组异步操作是否都结束了(不管成功或失败)。
所以,它的名字叫”Settled”,包含了”fufilled”和”rejected”两种情况.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <script> function ajax (url ) { return new Promise ((resolve, reject ) => { let xhr = new XMLHttpRequest (); xhr.open ('get' , url, true ); xhr.send (); xhr.onreadystatechange = function ( ) { if (xhr.readyState === 4 ) { if (xhr.status >= 200 && xhr.status < 300 ) { resolve (xhr.responseText ); } else { reject (xhr.responseText ); } } } }) } Promise .allSettled ([ajax ('http://www.xiongmaoyouxuan.com/api/tabs' ), ajax ('https://m.maizuo.com/gateway?cityId=110100&k=4770248' ) ]).then (value => { let successList = value.filter (item => item.status === 'fulfilled' ); console .log (successList) let errorList = value.filter (item => item.status === 'rejected' ); console .log (errorList) }).catch (error => { console .log (error); }) </script>
9.7 Promise.any() 只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfiilled状态;
如果所有参数实例都变成rejected,包装实例就会变成rejected状态。
Promise.any()跟Promise.race()方法很像,但是有一点不同,
就是Promise.any()不会因为某个Promise变成rejected状态而结束,
必须等到所有参数Promise变成rejected状态才会结束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <script> let p1 = new Promise ((resolve, reject ) => { setTimeout (() => { resolve ('ok' ); }, 1000 ) }) let p2 = new Promise ((resolve, reject ) => { setTimeout (() => { resolve ('okk' ); }, 2000 ) }) let p3 = new Promise ((resolve, reject ) => { setTimeout (() => { reject ('error' ); }, 3000 ) }) Promise .any ([p1, p2, p3]).then (res => { console .log (res) }).catch (err => { console .log ('error' ) }) </script>
9.8 Promise.finally() finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象变成fufilled还是rejected状态,最终都会被执行。
finally方法中的回调函数
是不接受参数的,因为无论前面是fulfilled状态还是rejected状态, 它都是执行。
1 2 3 4 5 6 7 8 9 10 11 const p = new Promise ((resolve, reject ) => { reject ('error' ); }); p.then (res => { console .log (res); }).catch (err => { console .log (err); }).finally (() => { console .log ('finally' ) })
十、终止Promise链条 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 new Promise ((resolve, reject ) => { resolve (111 ); }).then (value => { console .log (value); console .log (222 ); return new Promise ((resolve, reject ) => {}); }).then (value => { console .log (333 ); }).then (value => { console .log (444 ); }).catch (reason => { console .log (reason); });
十一、几个关键问题 11.1 如何修改 promise 对象状态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <script> let p = new Promise ((resolve, reject ) => { resolve ('ok' ); reject ('error' ); }); console .log (p); </script>
11.2 指定多个回调执行情况 问题:一个promise指定多个成功/失败回调函数,都会调用吗?
答:会,但是前提是当promise对象的状态改变(fulfilled/rejected)时才会调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <script> let p = new Promise ((resolve, reject ) => { resolve ('OK' ); }); p.then (value => { console .log (value); }, reason => { console .error (reason); }); p.then (value => { alert (value); }, reason => { alert (reason); }) </script>
11.3 指定回调与改变状态先后顺序问题 改变promise状态和指定回调函数执行谁先谁后?
11.4 promise.then()返回的新promise的结果状态由什么决定?
简单表达:由then指定的回调函数执行的结果决定
详细表达:
如果抛出异常:新promise对象状态变成rejected,reason为抛出的异常
如果返回的是是非promise的任意值,新promise对象状态变成fulfilled,value为返回的值
如果返回的是另一个新的promise对象,此promise的结果就会称为新promise的结果
1 2 3 4 5 6 7 8 9 10 11 12 const p = new Promise ((resolve, reject ) => { resolve ('ok' ); }) let result = p.then (value => { return new Promise ((resolve, reject ) => { resolve ('okk' ); }) }, reason => { console .log (reason); }) console .log (result);
11.5 promise如何串联多个操作任务?
promise的then()返回一个新的promise对象,可以写成then()方法的链式调用
通过then()的链式调用串联多个同步/异步任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <script> new Promise ((resolve, reject ) => { console .log (111 ); reject (); }).then (value => { console .log (222 ); }).then (value => { console .log (value); }).then (value => { console .log (value) }, reason => { console .error (reason); }); </script>
11.6 promise的异常穿透
当使用promise的then链式调用时, 可以在最后指定失败的回调,
前面任何操作出了异常, 都会传到最后失败的回调中处理
1 2 3 4 5 6 7 8 9 10 11 12 new Promise ((resolve, reject ) => { console .log (111 ); reject ('error' ); }).then (value => { console .log (222 ); }).then (value => { console .log (value); }).then (value => { console .log (value) }).catch (reason => { console .log (reason); })
11.7 中断promise链
当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
办法: 在回调函数中返回一个pending状态的promise对象
1 2 3 4 5 6 7 8 9 10 11 12 13 new Promise ((resolve, reject ) => { console .log (111 ); resolve ('ok' ); }).then (value => { console .log (222 ); }).then (value => { console .log (value); return new Promise (() => { }) }).then (value => { console .log (value) }, reason => { console .error (reason); });
十二、async和await async/await 是ES7提出的基于Promise的解决异步的最终方案。
12.1 async函数 async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。
因此对async函数可以直接then,返回值就是then方法传入的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 async function fun0 ( ){ console .log (1 ); return 1 ; } fun0 ().then (val => { console .log (val) }) async function fun1 ( ){ console .log ('Promise' ); return new Promise (function (resolve,reject ){ resolve ('Promise' ) }) } fun1 ().then (val => { console .log (val); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 async function main ( ) { console .log ('async function' ); return 'hahaha' ; } let result = main ().then (value => { console .log (value); }); console .log (result);
12.2 await表达式 await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待 。
await 修饰的如果是Promise对象,可以获取Promise中返回的内容(resolve或reject的参数),且取到值后语
句才会往下执行;如果不是Promise对象:把这个非promise的东西当做await表达式的结果。
注意事项
await必须写在async函数中,但是async函数中可以没有await
如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
1 2 3 4 5 6 7 8 9 10 11 12 13 async function fun ( ){ let a = await 1 ; let b = await new Promise ((resolve,reject )=> { setTimeout (function ( ){ resolve ('setTimeout' ) },3000 ) }) let c = await function ( ){ return 'function' }() console .log (a,b,c) } fun ();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function log (time ){ setTimeout (function ( ){ console .log (time); return 1 ; },time) } async function fun ( ){ let a = await log (1000 ); let b = await log (3000 ); let c = log (2000 ); console .log (a); console .log (1 ) } fun ();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 async function main ( ) { var rs = await 10 ; var rs = await 1 + 1 ; var rs = await "非常6+7" ; var rs = await new Promise ((resolve, reject ) => { resolve ('success' ); }) try { var rs = await new Promise ((resolve, reject ) => { reject ('error' ); }) } catch (e) { console .log (e); } } main ();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function getSomeThing ( ){ return new Promise ((resolve,reject )=> { setTimeout (()=> { resolve ('获取成功' ) },3000 ) }) } async function test ( ){ let a = await getSomeThing (); console .log (a) } test ();
案例:async结合await读取文件内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const fs = require ('fs' );const {promisify} = require ('util' );const myreadfile = promisify (fs.readFile );async function main ( ){ try { let one = await myreadfile ('./resource/4.html' ); let two = await myreadfile ('./resource/2.html' ); let three = await myreadfile ('./resource/3.html' ); console .log (one + two + three); }catch (e){ console .log (e); } } main ();
十三、JS中的宏队列与微队列
说明
JS中用来存储待执行回调函数的队列包含2个不同特定的列队
宏列队: 用来保存待执行的宏任务(回调), 比如: 定时器回调/DOM事件回调/ajax回调
微列队: 用来保存待执行的微任务(回调), 比如: promise的回调/MutationObserver的回调
JS执行时会区别这2个队列
JS引擎首先必须先执行所有的初始化同步任务代码
每次准备取出第一个宏任务执行前, 都要将所有的微任务一个一个取出来执行
1 2 3 4 5 6 7 8 9 10 11 12 13 setTimeout (() => { console .log (111 ); }); new Promise ((resolve, reject ) => { resolve (); reject (); console .log (222 ); }).then (v => { console .log (333 ); }) console .log (444 );
十四、Promise常见面试题 1 2 3 4 5 6 7 8 9 10 setTimeout (() => { console .log (1 ) }, 0 ) Promise .resolve ().then (() => { console .log (2 ) }) Promise .resolve ().then (() => { console .log (4 ) }) console .log (3 )
1 2 3 4 5 6 7 8 9 10 11 12 setTimeout (() => { console .log (1 ) }, 0 ) new Promise ((resolve ) => { console .log (2 ) resolve () }).then (() => { console .log (3 ) }).then (() => { console .log (4 ) }) console .log (5 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const first = ( ) => (new Promise ((resolve, reject ) => { console .log (3 ) let p = new Promise ((resolve, reject ) => { console .log (7 ) setTimeout (() => { console .log (5 ) resolve (6 ) }, 0 ) resolve (1 ) }) resolve (2 ) p.then ((arg ) => { console .log (arg) }) })) first ().then ((arg ) => { console .log (arg) }) console .log (4 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 setTimeout (() => { console .log ("0" ) }, 0 ) new Promise ((resolve, reject ) => { console .log ("1" ) resolve () }).then (() => { console .log ("2" ) new Promise ((resolve, reject ) => { console .log ("3" ) resolve () }).then (() => { console .log ("4" ) }).then (() => { console .log ("5" ) }) }).then (() => { console .log ("6" ); }) new Promise ((resolve, reject ) => { console .log ("7" ) resolve () }).then (() => { console .log ("8" ) });
十五、手写promise自定义基础结构的搭建 15.1 Promise 的基本结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (function (window ){ function Promise (executor ){ executor (function ( ){ },function ( ){ }); } window .Promise = Promise ; })(window );
1 2 3 4 new Promise ((resolve, reject )=> { console .log ("这是我的执行器函数" ,resolve,reject) }) console .log ("over" ,Promise );
15.2 Promise实例拥有两个实例属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; executor (function ( ){ },function ( ){ }); } window .Promise = Promise ; })(window );
1 2 3 4 const p1 = new Promise ((resolve, reject )=> { console .log ("这是我的执行器函数" ,resolve,reject) }) console .log (p1);
15.3 更改状态三种方式-方法未抽离
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; try { executor (function (value ){ this .state = "fulfilled" ; this .result = value; }.bind (this ),function (value ){ this .state = "rejected" ; this .result = value; }.bind (this )); }catch (err){ this .state = "rejected" ; this .result = err; } } window .Promise = Promise ; })(window );
1 2 3 4 5 6 const p1 = new Promise ((resolve, reject )=> { throw "异常" }) console .log (p1);
15.4 更改状态三种方式-抽离为普通函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = function (value ){ this .state = "fulfilled" ; this .result = value; }.bind (this ) const _reject = function (value ){ this .state = "rejected" ; this .result = value; }.bind (this ) try { executor (_resolve,_reject); }catch (err){ this .state = "rejected" ; this .result = err; } } window .Promise = Promise ; })(window );
1 2 3 4 5 6 const p1 = new Promise ((resolve, reject )=> { reject (2 ); }) console .log (p1);
15.5 更改状态三种方式-抽离为箭头函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ this .state = "fulfilled" ; this .result = value; } const _reject = value=>{ this .state = "rejected" ; this .result = value; } try { executor (_resolve,_reject); }catch (err){ this .state = "rejected" ; this .result = err; } } window .Promise = Promise ; })(window );
1 2 3 4 5 6 const p1 = new Promise ((resolve, reject )=> { throw "异常" }) console .log (p1);
15.6 状态只允许更改一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } window .Promise = Promise ; })(window );
1 2 3 4 5 6 const p1 = new Promise ((resolve, reject )=> { resolve (1 ); reject (2 ); throw "异常" }) console .log (p1);
15.7 then函数调用成功或失败回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (this .state === "fulfilled" ){ onResolved (this .result ); }else if (this .state === "rejected" ){ onRejected (this .result ); } }, catch (){ } }) window .Promise = Promise ; })(window );
15.8 then函数中的回调函数是异步调用的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (this .state === "fulfilled" ){ setTimeout (()=> { onResolved (this .result ); }) }else if (this .state === "rejected" ){ setTimeout (()=> { onRejected (this .result ); }) } }, catch (){ } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 const p1 = new Promise ((resolve, reject )=> { throw "异常" }) p1.then (value => { console .log ("成功回调" ,value); },reason => { console .log ("失败回调" ,reason); }) console .log ("over" );
15.9 then函数返回的是一个Promise实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ return new Promise ((resolve,reject )=> { if (this .state === "fulfilled" ){ setTimeout (()=> { onResolved (this .result ); }) }else if (this .state === "rejected" ){ setTimeout (()=> { onRejected (this .result ); }) } }) }, catch (){ } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 const p1 = new Promise ((resolve, reject )=> { throw "异常" }) const p2 = p1.then (value => { console .log ("成功回调" ,value); },reason => { console .log ("失败回调" ,reason); }) console .log (p2);
15.10 then函数返回的Promise实例状态以及值-未优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ return new Promise ((resolve,reject )=> { if (this .state === "fulfilled" ){ setTimeout (()=> { try { const value = onResolved (this .result ); if (value instanceof Promise ){ value.then (resolve,reject) }else { resolve (value); } }catch (err){ reject (err); } }) }else if (this .state === "rejected" ){ setTimeout (()=> { try { const value = onRejected (this .result ); if (value instanceof Promise ){ value.then (resolve,reject); }else { resolve (value); } }catch (err){ reject (err); } }) } }) }, catch (){ } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const p1 = new Promise ((resolve, reject )=> { reject (2 ); }) const p2 = p1.then (value => { return new Promise ((resolve,reject )=> { throw "异常2" }) },reason => { return new Promise ((resolve,reject )=> { throw "异常3" }) }) console .log (p2);
15.11 then函数返回的Promise实例状态以及值-优化封装函数_common 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ){ value.then (resolve,reject); }else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); } }) }, catch (){ } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const p1 = new Promise ((resolve, reject )=> { reject (2 ); }) const p2 = p1.then (value => { throw "异常2" },reason => { }) console .log (p2);
15.12 增加成功与失败回调函数的默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 (function (window ){ function Promise (executor ){ this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ){ value.then (resolve,reject); }else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); } }) }, catch (){ } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 const p1 = new Promise ((resolve,reject )=> { resolve (1 ); }) const p2 = p1.then ();console .log (p2);
15.14 执行器函数常用于处理异步行为 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 (function (window ){ function Promise (executor ){ this .callbackFn = {}; this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; if (this .callbackFn .onResolved ){ this .callbackFn .onResolved (); } } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; if (this .callbackFn .onRejected ){ this .callbackFn .onRejected (); } } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) value.then (resolve,reject); else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); }else { this .callbackFn = { onResolved :_common.bind (this ,onResolved), onRejected :_common.bind (this ,onRejected) } } }) }, catch (){ } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 const p1 = new Promise ((resolve,reject )=> { setTimeout (()=> { reject (100 ); }) }) p1.then (value => { console .log (value); },reason => { console .log ("失败" ,reason); })
15.15 可以指定多个成功或失败的回调 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 (function (window ){ function Promise (executor ){ this .callbackFn = []; this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved () }) } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected () }) } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) value.then (resolve,reject); else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); }else { this .callbackFn .push ({ onResolved :_common.bind (this ,onResolved), onRejected :_common.bind (this ,onRejected) }) } }) }, catch (){ } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 const p1 = new Promise ((resolve,reject )=> { setTimeout (()=> { reject (100 ); }) }) p1.then (value => { console .log ("成功1" ,value); },reason => { console .log ("失败1" ,reason); }) p1.then (value => { console .log ("成功2" ,value); },reason => { console .log ("失败2" ,reason); }) p1.then (value => { console .log ("成功3" ,value); },reason => { console .log ("失败3" ,reason); }) p1.then (value => { console .log ("成功4" ,value); },reason => { console .log ("失败4" ,reason); })
15.16 catch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 (function (window ){ function Promise (executor ){ this .callbackFn = []; this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved () }) } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected () }) } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) value.then (resolve,reject); else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); }else { this .callbackFn .push ({ onResolved :_common.bind (this ,onResolved), onRejected :_common.bind (this ,onRejected) }) } }) }, catch (onRejected){ return this .then (undefined ,onRejected) } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const p1 = new Promise ((resolve,reject )=> { setTimeout (()=> { reject (100 ); }) }) const p2 = p1.catch (reason => { return new Promise ((resolve,reject )=> { resolve (2 ); }) }) console .log (p2);
15.17 链式调用支持 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 (function (window ){ function Promise (executor ){ this .callbackFn = []; this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved () }) } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected () }) } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) value.then (resolve,reject); else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); }else { this .callbackFn .push ({ onResolved :_common.bind (this ,onResolved), onRejected :_common.bind (this ,onRejected) }) } }) }, catch (onRejected){ return this .then (undefined ,onRejected) } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 new Promise ((resolve,reject )=> { resolve (1 ); }).then (value => { console .log (value); return 2 ; }).then (value => { console .log (value); return 3 ; }).then (value => { console .log (value); return 4 ; }).then (value => { console .log (value); return 5 ; })
15.18 异常穿透支持 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 (function (window ){ function Promise (executor ){ this .callbackFn = []; this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved () }) } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected () }) } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) value.then (resolve,reject); else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); }else { this .callbackFn .push ({ onResolved :_common.bind (this ,onResolved), onRejected :_common.bind (this ,onRejected) }) } }) }, catch (onRejected){ return this .then (undefined ,onRejected) } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 new Promise ((resolve, reject ) => { resolve (1 ); }).then (value => { throw "异常" }).then (value => { console .log (value); return 3 ; }).then (value => { console .log (value); return 4 ; }).then (value => { console .log (value); return 5 ; }).catch (reason => { console .log (4 ,reason); })
15.19 中断Promise链 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 (function (window ){ function Promise (executor ){ this .callbackFn = []; this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved () }) } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected () }) } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) value.then (resolve,reject); else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); }else { this .callbackFn .push ({ onResolved :_common.bind (this ,onResolved), onRejected :_common.bind (this ,onRejected) }) } }) }, catch (onRejected){ return this .then (undefined ,onRejected) } }) window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 new Promise ((resolve,reject )=> { resolve (1 ); }).then (value => { console .log (value); return 2 ; }).then (value => { console .log (value); return new Promise (()=> {}) }).then (value => { console .log (value); return 4 ; }).then (value => { console .log (value); return 5 ; })
15.20 resolve 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 (function (window ){ function Promise (executor ){ this .callbackFn = []; this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved () }) } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected () }) } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) value.then (resolve,reject); else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); }else { this .callbackFn .push ({ onResolved :_common.bind (this ,onResolved), onRejected :_common.bind (this ,onRejected) }) } }) }, catch (onRejected){ return this .then (undefined ,onRejected) } }) Promise .resolve = function (value ){ if (value instanceof Promise ){ return value; }else { return new Promise (resolve => { resolve (value); }) } } window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const p =new Promise ((resolve,reject )=> { reject (2 ); }) const p1 = Promise .resolve (p);console .log (p1===p);
15.21 reject 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 (function (window ){ function Promise (executor ){ this .callbackFn = []; this .state = "pending" ; this .result = undefined ; const _resolve = value=>{ if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved () }) } const _reject = value=>{ if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected () }) } try { executor (_resolve,_reject); }catch (err){ _reject (err); } } Object .assign (Promise .prototype ,{ then (onResolved,onRejected ){ if (!(onResolved instanceof Function )){ onResolved = value => value; } if (!(onRejected instanceof Function )){ onRejected = reason => { throw reason; }; } return new Promise ((resolve,reject )=> { const _common = function (callback ){ setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) value.then (resolve,reject); else { resolve (value); } }catch (err){ reject (err); } }) } if (this .state === "fulfilled" ){ _common.call (this ,onResolved); }else if (this .state === "rejected" ){ _common.call (this ,onRejected); }else { this .callbackFn .push ({ onResolved :_common.bind (this ,onResolved), onRejected :_common.bind (this ,onRejected) }) } }) }, catch (onRejected){ return this .then (undefined ,onRejected) } }) Promise .resolve = function (value ){ if (value instanceof Promise ){ return value; }else { return new Promise (resolve => { resolve (value); }) } } Promise .reject = function (value ){ return new Promise ((resolve,reject )=> { reject (value); }) } window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 const p1 = Promise .reject (1 );console .log (p1);const p2 = Promise .reject (new Promise ((resolve,reject )=> { resolve (2 ); })); console .log (p2);const p3 = Promise .reject (new Promise ((resolve,reject )=> { reject (2 ); })); console .log (p3);
15.22 完成all 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 (function (window ) { function Promise (executor ) { this .state = "pending" ; this .result = undefined ; this .callbackFn = []; const _resolve = value => { if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved (); }) } const _reject = value => { if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected (); }) } try { executor (_resolve, _reject); } catch (err) { _reject (err); } } Object .assign (Promise .prototype , { then (onResolved, onRejected ) { if (!(onResolved instanceof Function )) onResolved = value => value; if (!(onRejected instanceof Function )) onRejected = reason => { throw reason }; return new Promise ((resolve, reject ) => { const _common = function (callback ) { setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) { value.then (resolve, reject); } else { resolve (value); } } catch (err) { reject (err); } }) } if (this .state === "fulfilled" ) _common.call (this , onResolved); else if (this .state === "rejected" ) _common.call (this , onRejected); else { this .callbackFn .push ({ onResolved : _common.bind (this , onResolved), onRejected : _common.bind (this , onRejected) }) } }) }, catch (onRejected){ return this .then (undefined ,onRejected); } }) Promise .resolve = function (value ){ if (value instanceof Promise ){ return value; }else { return new Promise (resolve => { resolve (value); }) } } Promise .reject = function (value ){ return new Promise ((resolve,reject )=> { reject (value); }) } Promise .all = function (promiseArr ){ let index = 0 ; let successArr = new Array (promiseArr.length ); return new Promise ((resolve,reject )=> { promiseArr.forEach ((value,i )=> { value.then (v => { index++; successArr[i] = v; if (index === promiseArr.length ){ resolve (successArr); } },s => { reject (s); }) }) }) } window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 const p1 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (100 ) },100 ) }) const p2 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (200 ) },50 ) }) const p3 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (300 ) },200 ) }) const p4 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (400 ) },100 ) }) const p = Promise .all ([p1,p2,p3,p4]);console .log (p);
15.23 完成race 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 (function (window ) { function Promise (executor ) { this .state = "pending" ; this .result = undefined ; this .callbackFn = []; const _resolve = value => { if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved (); }) } const _reject = value => { if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected (); }) } try { executor (_resolve, _reject); } catch (err) { _reject (err); } } Object .assign (Promise .prototype , { then (onResolved, onRejected ) { if (!(onResolved instanceof Function )) onResolved = value => value; if (!(onRejected instanceof Function )) onRejected = reason => { throw reason }; return new Promise ((resolve, reject ) => { const _common = function (callback ) { setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) { value.then (resolve, reject); } else { resolve (value); } } catch (err) { reject (err); } }) } if (this .state === "fulfilled" ) _common.call (this , onResolved); else if (this .state === "rejected" ) _common.call (this , onRejected); else { this .callbackFn .push ({ onResolved : _common.bind (this , onResolved), onRejected : _common.bind (this , onRejected) }) } }) }, catch (onRejected){ return this .then (undefined ,onRejected); } }) Promise .resolve = function (value ){ if (value instanceof Promise ){ return value; }else { return new Promise (resolve => { resolve (value); }) } } Promise .reject = function (value ){ return new Promise ((resolve,reject )=> { reject (value); }) } Promise .all = function (promiseArr ){ let index = 0 ; let successArr = new Array (promiseArr.length ); return new Promise ((resolve,reject )=> { promiseArr.forEach ((value,i )=> { value.then (v => { index++; successArr[i] = v; if (index === promiseArr.length ){ resolve (successArr); } },s => { reject (s); }) }) }) } Promise .race = function (promiseArr ){ return new Promise ((resolve,reject )=> { promiseArr.forEach (value => { value.then (resolve,reject); }) }) } window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const p1 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (100 ) },100 ) }) const p2 = new Promise ((resolve,reject )=> { setTimeout (()=> { reject (200 ) },50 ) }) const p3 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (300 ) },200 ) }) const p4 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (400 ) },100 ) }) const p = Promise .race ([p1,p2,p3,p4]);console .log (p);
15.24 class版本实现Promise 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 (function (window ) { class Promise { static resolve (value ){ if (value instanceof Promise ){ return value; }else { return new Promise (resolve => { resolve (value); }) } } static reject (value ){ return new Promise ((resolve,reject )=> { reject (value); }) } static all (promiseArr ){ let index = 0 ; let successArr = new Array (promiseArr.length ); return new Promise ((resolve,reject )=> { promiseArr.forEach ((value,i )=> { value.then (v => { index++; successArr[i] = v; if (index === promiseArr.length ){ resolve (successArr); } },s => { reject (s); }) }) }) } static race (promiseArr ){ return new Promise ((resolve,reject )=> { promiseArr.forEach (value => { value.then (resolve,reject); }) }) } constructor (executor ) { this .state = "pending" ; this .result = undefined ; this .callbackFn = []; const _resolve = value => { if (this .state !== "pending" ) return ; this .state = "fulfilled" ; this .result = value; this .callbackFn .forEach (item => { item.onResolved (); }) } const _reject = value => { if (this .state !== "pending" ) return ; this .state = "rejected" ; this .result = value; this .callbackFn .forEach (item => { item.onRejected (); }) } try { executor (_resolve, _reject); } catch (err) { _reject (err); } } then (onResolved, onRejected ) { if (!(onResolved instanceof Function )) onResolved = value => value; if (!(onRejected instanceof Function )) onRejected = reason => { throw reason }; return new Promise ((resolve, reject ) => { const _common = function (callback ) { setTimeout (()=> { try { const value = callback (this .result ); if (value instanceof Promise ) { value.then (resolve, reject); } else { resolve (value); } } catch (err) { reject (err); } }) } if (this .state === "fulfilled" ) _common.call (this , onResolved); else if (this .state === "rejected" ) _common.call (this , onRejected); else { this .callbackFn .push ({ onResolved : _common.bind (this , onResolved), onRejected : _common.bind (this , onRejected) }) } }) } catch (onRejected){ return this .then (undefined ,onRejected); } } window .Promise = Promise ; })(window );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const p1 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (100 ) },100 ) }) const p2 = new Promise ((resolve,reject )=> { setTimeout (()=> { reject (200 ) },50 ) }) const p3 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (300 ) },200 ) }) const p4 = new Promise ((resolve,reject )=> { setTimeout (()=> { resolve (400 ) },100 ) }) const p = Promise .race ([p1,p2,p3,p4]);console .log (p);