JS的Promise大兄弟

一,认识Promise

  相信用过JS的都知道JS是单线程的,同步的函数先执行,异步的函数先加入到一个队列中等同步执行完了再执行异步函数。基于这个JS采用异步回调的方式来处理需要等待的事件,是的代码会继续执行而不用在异步处理的地方一直等待着。同时也带来一个不好的方面,如果我们有很多的回调函数, 也就是说一个回调函数里边再嵌套一个回调一层一层的嵌套,这样就很容易进入传说中的回调地狱。

  注意:异步和回调不是一个东西

  下面感受一下回调地狱代码的魅力:

 1 async(1, function(value){
 2   async(value, function(value){
 3     async(value, function(value){
 4       async(value, function(value){
 5         async(value, function(value){
 6           async(value, final);
 7         });
 8       });
 9     });
10   });
11 });

  是挺有美感的但是阅读性很差,写法也让人感到无力,es6新出的promise对象已经es7的async await都可以解决这个问题,但是今天的主角是Promise。

  Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件。ES6统一了用法,并原生提供了Promise对象。作为对象,Promise有一下两个特点:(1)对象的状态不受外界影响;(2)一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态。Promise有三种状态,分别是:Pending(进行中),Resolved(完成),Rejected (失败)。Promise从Pending状态开始,如果成功就转到成功态,并执行resolve回调函数;如果失败就转到失败状态并执行reject回调函数。

  Promise一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

二.使用Promise  

  Promise构造函数接收一个函数作为参数,该函数的两个参数是resolvereject,它们由JavaScript引擎提供。其中resolve函数的作用是当Promise对象转移到成功,调用resolve并将操作结果作为其参数传递出去;reject函数的作用是单Promise对象的状态变为失败时,将操作报出的错误作为其参数传递出去

  介绍一下Promise的api怎么使用:

  1、Promise.resolve()的作用将现有对象转为Promise对象resolved;Promise.resolve(‘test‘)==new Promise(resolve=>resolve(‘test‘))

  2、Promise.reject()返回一个Promise对象,状态为rejected

  3、Promise.prototype.then()方法接受两个参数,第一个是成功的resolved的回调,另一个是失败rejected的回调,第二个失败的回调参数可选。并且then方法里也可以返回promise对象,这样就可以链式调用了。

 1 function judgeNumber(num){
 2     var promise1 = new Promise(function(resolve,reject){
 3         num =5;
 4         if(num<5){
 5             resolve("num小于5,值为:"+num);
 6         }else{
 7             reject("num不小于5,值为:"+num);
 8         }
 9     });
10     return promise1;
11 }
12 
13 judgeNumber().then(
14     function(message){
15         console.log(message);
16     },
17     function(message){
18         console.log(message);
19     }
20 )

包含有两个方法,前一个执行resolve回调的参数,后一个执行reject回调的参数。

  4、Promise.prototype.catch()发生错误的回调函数。

 1 function judgeNumber(num){
 2     var promise1 = new Promise(function(resolve,reject){
 3         num =5;
 4         if(num<5){
 5             resolve("num小于5,值为:"+num);
 6         }else{
 7             reject("num不小于5,值为:"+num);
 8         }
 9     });
10     return promise1;
11 }
12 
13 judgeNumber().then(
14     function(message){
15         console.log(message);
16     }
17 )
18 .catch(function(message){
19     console.log(message);
20 })
这个时候catch执行的是和reject一样的,也就是说如果Promise的状态变为reject时,会被catch捕捉到,
不过需要特别注意的是如果前面设置了reject方法的回调函数,·则catch不会捕捉到状态变为reject的情况。
catch还有一点不同的是,如果在resolve或者reject发生错误的时候,会被catch捕捉到,
这与java,c++的错误处理时一样的,这样就能避免程序卡死在回调函数中了。

  5、Promise.all() // 所有的都有完成,相当于 且,适合用于所有的结果都完成了才去执行then()成功的操作。

 1 let p1 =new Promise(function(resolve,reject){
 2             resolve(1);
 3         });
 4         let p2 = new Promise(function(resolve,reject){
 5             resolve(2);
 6         });
 7         let p3 = new Promise(function(resolve,reject){
 8             resolve(3);
 9         });
10         Promise.all([p1, p2, p3]).then(function (results) {
11             console.log(‘success:‘+results);   //success:1,2,3
12         }).catch(function(r){
13             console.log("error");
14             console.log(r);
15         });

  6、Promise.race() // 完成一个即可,相当于 或。(这个经常用在一些图片比较多得网站)

 1 //模拟请求某个图片资源
 2 function requestImg(){
 3     var p = new Promise(function(resolve, reject){
 4         var img = new Image();
 5         img.onload = function(){
 6             resolve(img);
 7         }
 8         img.src = ‘yingaxiang‘;
 9     });
10     return p;
11 }
12 
13 //延时函数,用于给请求计时
14 function timeout(){
15     var p = new Promise(function(resolve, reject){
16         setTimeout(function(){
17             reject(‘图片请求超时‘);
18         }, 5000);
19     });
20     return p;
21 }
22 
23 Promise
24 .race([requestImg(), timeout()])
25 .then(function(results){
26     console.log(results);
27 })
28 .catch(function(reason){
29     console.log(reason);
30 });
这样就相当于requestImg方法与timeout方法的龟兔赛跑,如果五秒内图片请求成功了那么就会进入.then中,如果五秒内请求图片不成功则将进入.catch中提示请求超时

 

Promise Ajax

 1 function ajax(URL) {
 2     return new Promise(function (resolve, reject) {
 3         var req = new XMLHttpRequest(); 
 4         req.open(‘GET‘, URL, true);
 5         req.onload = function () {
 6         if (req.status === 200) { 
 7                 resolve(req.responseText);
 8             } else {
 9                 reject(new Error(req.statusText));
10             } 
11         };
12         req.onerror = function () {
13             reject(new Error(req.statusText));
14         };
15         req.send(); 
16     });
17 }
18 var URL = "https://www.cnblogs.com/yingaxiang/"; 
19 ajax(URL).then(function onFulfilled(value){
20     document.write(‘内容是:‘ + value); 
21 }).catch(function onRejected(error){
22     document.write(‘错误:‘ + error); 
23 });

 

JS的Promise大兄弟

上一篇:flask框架之动态构建URL


下一篇:11HTML属性变化