Promise小结


   Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) 、Resolved(已经完成)和Rejected(已失败)

ES6规定,Promise对象是一个构造函数,用来生成Promise实例。

1
2
3
4
5
6
7
var  promise= new  Promise( function (resove,reject){
      if  ( /* 异步操作成功 */ ){
     resolve(value);
   else  {
     reject(error);
   }
})

Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。

1
2
3
4
5
promise.then( function (value) {
   // success
},  function (error) {
   // failure
});

案例

1
2
3
4
5
6
7
var  promise= new  Promise( function (resolve,reject){
          console.log( 'promise' );
      })
      promise.then( function (){
         console.log( '我后执行' )
      })
      console.log( '我先执行' )<br><br> //上面代码中,Promise新建后立即执行,所以首先输出的是“Promise”。然后,<code>then</code>方法指定的回调函数,<br>//将在当前脚本所有同步任务执行完才会执行,所以“我后执行” 最后输出。

 ajax

var  http = {
     get:  function (url) {
         var  promise =  new  Promise( function (resolve, reject) {
             $.ajax({
                 url: url,
                 method:  'get' ,
                 success:  function (data) {
                     resolve(data);
                 },
                 error:  function (xhr, statusText) {
                     reject(statusText);
                 }
             });
         });
         return  promise;
     }
};
http.get( 'solve.php' ).then( function (data) {
     return  data;
},  function (err) {
     return  Promise.reject( 'Sorry, file not Found.' );
}).then( function (data) {
     document.write(data);
},  function (err) {
     document.write(err);
});

复制代码
 1      var getJSON=function(url){
 2         var promise=new Promise(function(resolve,reject){
 3             var xhr=new XMLHttpRequest();
 4             xhr.open('get',url);
 5             xhr.onreadystatechange=handler;
 6             xhr.send(null);
 7 
 8             function handler(){
 9                 if(this.readystate!==4){
10                     return;
11                 }
12                 if(this.status==200){
13                     resolve(this.responseText)
14                 }else{
15                     reject(new Error(this.statusText));
16                 }
17             }
18         })
19           return promise;
20      }
21     getJSON("/get.json").then(function(json) {
22       console.log('Contents: ' + json);
23     }, function(error) {
24       console.error('出错了', error);
25     });
复制代码

 

 

 

Promise三种状态

pending、resolved、rejected

使用语法

var promis = new Promise(function(resolve,reject){ $.ajax({ url:'/api/something.json', method:'get', datatype:'json', success:(res) =>{ resolve(res) }, error:(err)=>{ reject(err) } }) }) promis.then(function(res){ console.log(res) }).catch(function(err){ console.log(err) });

Promise.prototype.then()

链式调用,状态变为resolve
如果把下一步想要的东西return出去,即可让下一个then使用

var promise = new Promise(function(resolve,reject){ $.ajax({ url:'/api/poisearch.json', method:'get', datatype:'json', success:(res) =>{ resolve(res) }, error:(err)=>{ reject(err) } }) }) promise.then(function(res){ return res.data }).then(function(data){ return data.result; }).then(function(result){ console.log(result) });

上面的代码还可以借用箭头函数简写成,极大提升了代码的简洁性和可读性

promise.then(res => res.data) .then(data => data.result) .then(result => console.log(result));

Promise.prototype.catch()

如果异步操作抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误。

  1. 另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。
  2. 如果Promise状态已经变成Resolved,再抛出错误是无效的。
  3. catch方法返回的还是一个Promise对象,因此后面还可以接着调用then方法。

Promise.all()

多个Promise实例,包装成1个,有点类似Array.prototype.every()
用法:

var p = Promise.all([p1, p2, p3]);
  1. 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
  2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race()

多个Promise实例,包装成1个,有点类似Array.prototype.some()

  1. p1、p2、p3其中一个状态变成fulfilled,p的状态就会变成fulfilled
  2. 那个率先改变的Promise实例的返回值,就传递给p的回调函数。

done()、finally()

 

 

 

 

 

 

 

 

 

 

 

新的ES6中引入了promise的概念,目的是让回调更为优雅。层层嵌套的回调会让javascript失去美感和可读性,同时javascript也推荐采用链式的方式去书写函数调用。于是Promise就应运而生。Promise即承诺的意思,new一个Promise就是新建一个承诺。在新建一个承诺的时候你需要做两件事情:

  1.指定承诺所需完成的事

  2.设置承诺是否实现的标准

下面我们来定义一个承诺:

  1.承诺的内容:“获取data.php的数据”,

  2.承诺是否实现的评判是:是否获取data.php的数据 ”

这里我们会用到jQuery.ajax()方法,这会让我们的代码显得简单精炼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var  http = {
     get:  function (url) {
         var  promise =  new  Promise( function (resolve, reject) {
             $.ajax({
                 url: url,
                 method:  'get' ,
                 success:  function (data) {
                     resolve(data);
                 },
                 error:  function (xhr, statusText) {
                     reject(statusText);
                 }
             });
         });
         return  promise;
     }
};
http.get( 'data.php' ).then( function (data) {
     document.write(data);
},  function (err) {
     document.write(err);
});

  这里是获取的data值

1
2
3
/* data.php文件 */
<?php
echo  '{"name":"Tom","age":"22"}' ;

  在http请求中,我们定义了一个get方法,在get方法中,我们定义了一个promise的对象,而不是直接直接使用ajax获取到我们想要的数据,在这个get方法,我们最后得到的是一个promise对象,对于这种需要等待的操作,我们采用promise去处理,返回给主线程的是一个promise对象,而不是一个最终的数据,这是延迟程序给主程序的一个承诺,主线程可以根据通过返回的promise对象获取数据或者处理错误。这使得异步处理变得优雅而简单。

  在jQuery.ajax()中,我们采用了两个方法来判断是否实现了我们的承诺,它们分别是resove和reject方法,如果如果jQuery.ajax()执行了success,并且返回的data中有数据,那么我们就判定这个承诺已经实现了(fulfilled),则调用resolve方法。如果jQuery.ajax()执行了error,那么我们就判定这个承诺被拒绝了(rejected),则调用reject方法。

那resove和reject这两个方法分别执行了哪些操作呢?这个我们就需要从Promise这个构造函数本身的结构说起。Promise这个构造函数结构大概是下面这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* 用于描述思维的代码 */
function  Promise(executor) {
     // 共有三种状态:pending(准备)、fulfilled(完成)、rejected(拒绝)
     this .PromiseStatus =  'pending' ;
     // 用于存储返回的数据
     this .PromiseValue;
     // 完成
     var  resolve =  function (reson) {};
     // 拒绝
     var  reject =  function (reson) {};
     ...
     // 开始执行承诺
     executor(resolve, reject);
}
Promise.prototype.then =  function () {};
Promise.prototype.chain =  function () {};
Promise.prototype. catch  function () {};
...

  

PromiseStatus:用于记录Promise对象的三种状态,这三中状态分别是:
pending:待定状态,Promise对象刚被初始化的状态
fulfilled:完成状态,承诺被完成了的状态
rejected:拒绝状态,承诺完成失败的状态
Promise的初始状态是pending。随后会更具承诺完成的情况更改PromiseStatus的值。

PromiseStatus:用于记录返回的数据或者错误。当承诺完成时,会把返回的数据赋给PromiseStatus。如果承诺执行失败了,那么失败的原因也会赋给此变量。

resolve()和reject():Promise构造函数中有两个闭包的函数resolve()和reject()。在new一个新的Promise的时候会传递一件你需要做的事情(executor)。这个executor是一个函数,在Promise的构造函数中它会被传入两个参数,这两个参数即我们的两个闭包的函数resolve()和reject(),以便你在executor中判定是否完成了你的承诺。

executor(): executor()函数中执行的代码就是子程序需要完成事。在executor()函数内如果调用了resolve(),resolve()则会把Promise对象的状态PromiseStatus修改为fulfilled,把resolve(value)中的value值赋给Promise对象的PromiseValue。然后再依次执行由then()方法构成的回调链中的回调函数。同样,在executor()中调用reject()的过程也是类似的。调用过程如下:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
/* 用于描述思维的代码 */
executor(resolve, reject) {
     ...
     resolve(value);
     ...
}
...
resolve(value) {
     PromiseStatus =  'fulfilled' ;
     PromiseValue = value;
     ...
     // 接着调用回调链中的回调函数
}

  

then(onFulfilled, onRejected):这个方法实际上是把onFulfilled()函数和onRejected()函数添加到Promise对象的回调链中。回调链就像一个由函数组构成的队列,每一组函数都是由至少一个函数构成(onFulfilled() 或者 onRejected() 或者 onFulfilled() 和 onRejected())。当resolve()或者reject()方法执行的时候,回调链中的回调函数会根据PromiseStatus的状态情况而被依次调用。

onFulfilled(value)和onRejected(reason):参数value和reason的实参都是PromiseValue。这里有一点值得注意,如果onFulfilled(value)和onRejected(reason)这两个回调函数中return返回值不是一个Promise的对象,那么这个返回值会被赋给PromiseValue,并在下一个then()的onFulfilled(value)和onRejected(reason)中做为实参使用。但如果这个返回值是一个Promise的对象,那么剩下的由then()构造的回调链会转交给新的Promise对象并完成调用。

有这样一个问题,如果在第一个then()中执行了onRejected(reason)回调函数,并且没有return任何值的时候,那么下一个then()中将会调用onFulfilled(value)方法,而不是onRejected(reason)。因为在执行上一个then()的onRejected(reason)回调函数的时候并没有出现错误或异常,所以PromiseStatus的状态就被更改为fulfilled了。为了避免这个问题,我们可以在onRejected(reson)中返回一个Promise对象并reject()。代码如下,我们要去访问一个并不存在的文件solve.php:

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
var  http = {
     get:  function (url) {
         var  promise =  new  Promise( function (resolve, reject) {
             $.ajax({
                 url: url,
                 method:  'get' ,
                 success:  function (data) {
                     resolve(data);
                 },
                 error:  function (xhr, statusText) {
                     reject(statusText);
                 }
             });
         });
         return  promise;
     }
};
http.get( 'solve.php' ).then( function (data) {
     return  data;
},  function (err) {
     return  Promise.reject( 'Sorry, file not Found.' );
}).then( function (data) {
     document.write(data);
},  function (err) {
     document.write(err);
});

  Promise.reject()方法会返回一个被reject()的Promise对象,因此使得我们可以继续走下一个then()中的onRejected(reason)方法。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM