参考资料传送门:戳一戳
1、是什么
Promise是异步编程的一种解决方案,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败);
一般成功了状态用resolved表示,失败用rejected表示。
Promise的返回值也是一个promise,会携带状态函数和函数带的参数,可进行链式操作new Promise(()=>{}).then(()=>{}).catch(()=>{});
注意:then()的返回值是新的promise,如果then执行了,catch是不会执行的,因此then可以由很多个,catch只有一个,中间有什么错误都会在catch抛出
2、为什么
为了让代码按照自己想要的执行过程进行渲染,比较多的是考虑到用ajax加载页面内容时dom元素未渲染完毕,javascript就加载完毕的,效果挂不到页面上的情况。
3、怎么做
(1)新建:2种方式
1 <script> 2 console.log(1); 3 const p1 = new Promise(function (resolve, reject) { 4 console.log(2); 5 }) 6 7 p1.then(()=>{console.log(3);}) 8 9 10 11 </script> 12 13 <script> 14 console.log(4); 15 </script> 16 <script> 17 function p(){ 18 return new Promise((resolved,rejected)=>{ 19 if(true){ 20 console.log(2); 21 resolved(6); 22 }else rejected(5); 23 }); 24 n.then((val)=>{ 25 //所有的都执行后再执行?! 26 console.log(3); 27 console.log(6); 28 }) 29 console.log(4); 30 } 31 //p(); 32 </script>
注意 第一个script片段的输出是1243,在then里面是输出3,这个代表浏览器会在当前脚本所有同步任务执行完才会执行then里面的回调函数,当前脚本是指同一个js文件或者同一个script标签内部。
(2)关于resolve,reject,then的使用
总结:resolve和reject的返回决定then调用哪个函数,然后可以带参数到then中
1 function timeout(ms) {
//new 一个promise对象,两个形参es6自动创建的,当里面的匿名函数执行成功,再调用resolve(),会执行then后面成功回调函数,失败的话是执行then后面的失败函数 2 return new Promise((resolve, reject) => { 3 setTimeout(resolve, ms, 'done');
//代码执行成功则会调用resolve()
//失败调用reject() 4 }); 5 } 6 //调用resolve
函数和reject
函数时带有参数,那么它们的参数会被传递给回调函数。reject
函数的参数通常是Error
对象的实例,表示抛出的错误
//reject(new Error(this.statusText));
7 timeout(100).then(("成功后执行的回调函数") => {8 console.log(value);
9 },("失败后执行的回调函数")=>{"我是执行失败的回调函数"}});
<script> console.log(1); const n=new Promise((resolved,rejected)=>{ if(true){ console.log(2); resolved(6); }else rejected(new Error(5)); }); n.then((val)=>{ //所有的都执行后再执行?! console.log(3); console.log(val) }) console.log(4); /*结果是12436*/ </script>
(3)then与catch
总结:如果then里面有写reject,则有错误会在then阶段抛出,如果没有写,就会把错误都统一用catch抛出
1 //第一种 2 const p1=new Promise((resolve,reject)=>{ 3 //resolve(1); 4 reject(0); 5 }) 6 p1.then((result)=>{console.log("then_"+result)}, 7 (result)=>{console.log("then_"+result)}) 8 9 //第二种 10 const p1=new Promise((resolve,reject)=>{ 11 //resolve(1); 12 reject(0); 13 }) 14 p1.then((result)=>{console.log(result)}) 15 .catch((result)=>{console.log("cathc_"+result)})
下面代码执行过程
***程序执行流程是
p1是第一个新建的promise对象,会立马执行,然后在3s后抛出一reject,在这个等待的过程中,p2会执行,然后在1s后抛出resolve(p1),由于p2值是另外一个p1,在2s后p2的指向是p1,p1的回调函数reject,所以执行catch的error函数,promise的返回值是一个promise对象
<script> const p1 = new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('222')), 3000) }) const p2 = new Promise(function (resolve, reject) { setTimeout(() => resolve(p1), 1000) }) //所以最终p2返回的内容promise对象是p1 p2 .then(result => console.log(result)) .catch(error => console.log("111")) </script>
(4)注意,调用resolve
或reject
并不会终结 Promise 的参数函数的执行。即使代码resolve写在最前面,也不会终止里面代码的执行,如果需要执行resolve后不执行后面的语句需要利用return来打断代码执行
(5)Promise.prototype.finally()
finally
方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
(6)promise.all()
里面可以写一个数组,如果是promise对象的数组,则如果对象全市完成all才会返回完成,只要有一个失败就会转回失败
4.小缺点
首先,无法取消Promise
,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise
内部抛出的错误,不会反应到外部。第三,当处于pending
状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。