理解Promise对象

Promise对象:

  • 一个保存异步操作事件的对象
  • 三种状态,Pending、Fulfilled、Rejected。状态只会由“Pending→Fulfilled”或者“Pending→Rejected”,且状态改变就不会再变
/*Promise对象是由一个构造函数生成实例,接受函数为参数
   函数的参数为resolve和reject。这两者,也是函数*/
   
var promise = new Promise ( function(resolve , reject){
    
    /*一些异步操作*/
    
    if/*异步操作成功*/){
        //当调用resolve函数的时候,Promise对象状态由,Pending → Fulfilled
        //将value值进行传递(一般是异步操作成功后的结果)
        resolve(value)
    }  
    else {
        //当调用reject函数的时候,Promise对象状态由,Pending → Rejected
        //将error值进行传递
        reject(error)
    }    
})    

总体上来说,Promise对象,更像是一个事件的容器,但Promise对象状态的改变并不受事件的完成而完成,而是由参数函数中的 resolve 和 reject 函数来指定它什么时候改变状态。

比如下面代码:

var promise = new Promise ( function(resolve , reject){

    let i = 0//标记事件已完成,传字符串resolved值给.then()处理
    resolve(i)
i += 1 }) .then( //then方法是指,当Promise状态由Pending改变为Resolved时,立即调用 (value) = > { console.log(value) } )

---------------------------------------------------------------
最后输出:
0

then()方法下面会继续讲,问题来了,上面代码“ i += 1”是否会运行呢?再看

var promise = new Promise ( function(resolve , reject){

    resolve()
    console.log('A')
    setTimeout(() => { console.log('B') }, 3000)

}) .then(() = > { console.log('Resolved') })
---------------------------------------------------------------
先后输出:
A
Resolved
B   //3000ms后输出B

Promise对象在状态改变后,内部的代码还是会运行。当内部同步任务全部执行完成后,再调用then()方法。因此前两行最先输出的是‘A’和‘Resolved’,由于B是一个异步事件,所以在3000ms后被调用输出。

如果想在状态改变后直接结束,不执行之后的语句,最好不要将异步操作放在状态改变语句之后!当然也可以这样:

var promise = new Promise ( function(resolve , reject){
    //在前面加上return
    return resolve()

    console.log('A')
    setTimeout(() => { console.log('B') }, 3000)

}) .then(() = > { console.log('Resolved') })
---------------------------------------------------------------
最后只输出:
Resolved

原型方法 —— then()

  • 该方法是定义在Promise对象原型上的方法,即Promise.prototype.then()
  • 且then()方法返回一个新Promise实例

顾名思义,Promise实例状态改变后,要做什么。该方法为其添加了回调函数。Promise实例有两种状态,自然也提供了两种回调(Resolved 和 Rejected)

上面已经简单涉及了该方法,这里整理一下:

var promise = new Promise ( function(resolve , reject){
    //做些什么...
    if/*异步操作成功*/){ resolve(value) }  
    else {  reject(error) }    
}) .then( 
    //then方法接受两个回调函数为参数,以下

    //第一个Promise实例变为Resolved状态调用
    //函数中的参数value,接受Promise实例中resolve(value)传递的value值
    (value) => { /*success*/ },

    //(可选)第二个Promise实例变为Rejected状态调用
    ////函数中的参数error,接受Promise实例中reject(error)传递的error值
    (error) = > { /*failure*/ }
)
  • then()的链式调用

上面说了then方法返回一个新的Promise实例,那么就可以promise.then().then().then().then().then().....这样的链式调用了。

var promise = new Promise ( function(resolve , reject){
    resolve(A)   
}) .then( (value) => {  //此处参数 value 接受 resolve(A) 中的传递值 A
    //输出A
    console.log(value)
    return B
}).then( (value) => {  //此处参数 value 接受上一级then()方法中return的值
    //输出B
    console.log(value)
}).then( (value) => {  //上一个then方法无return时
    //输出undefined
    console.log(value)
})
-----------------------------------------------------------------
先后在控制台上输出:
A
B
undefined

若then()方法中传入的不是函数,则在链式调用中,此then()方法会被忽略,值会传入下一个then方法中

var promise = new Promise ( function(resolve , reject){
    resolve(A)   
}) .then(1)  //这个then方法被忽略
  .then( (value) => {console.log(value)}  )
-----------------------------------------------------------------
控制台上输出:
A

 

原型方法 —— catch()

  • Promise对象原型方法,Promise.prototype.catch()
  • 等同于.then( null , reject(error) )
  • catch()方法返回一个Promise对象

一般应用如下

var promise = new Promise ( function(resolve , reject){
    if/*异步操作成功*/){ resolve(value)}  
    else { reject(new Error ('promise'))}    
}) .then( (value)=>{
    if/*异步操作成功*/){ return A }  
    else { throw new Error('error_A') }  
}).then( (value)=>{
    if/*异步操作成功*/){ return B }  
    else { throw new Error('error_B') }  
}).then( (value)=>{
    if/*异步操作成功*/){return C }  
    else { throw new Error('error_C') }  
}).catch( (error)=>{
    /*此处catch捕获以上从Promise对象到任意then方法所抛出的错误*/
    console.log(error) 
    //catch只能捕获被调用之前抛出的错误,之后的错误如'error_D'就无法捕获
}).then( (value)=>{
    //上面的catch返回一个Promise对象因此可以继续调用then方法 
    if/*异步操作成功*/){return D }  
    else { throw new Error('error_D') }  
})

静态方法

  • Promise.all()
  • Promise.race()
  • Promise.resolve()
  • Promise.reject()

Promise.all()

将多个Promise实例包装,并且返回一个新的Promise实例

当包装中所有的Promise状态都变为Resolved时,返回结果数组,数组中返回值的顺序安装包装的数据排列

Promise.all([
   promise_A,
   promise_B,
   promise_C 
]).then(result=>{
  console.log(result)
})
---------------------------
//当promise_A,promise_B,promise_C状态都为Resolved时,result输出一个结果数组:
[result_A,result_B,resultC]

当Promise集合中有一个Promise最终状态为Rejected,就会被Promise.all()的catch方法进行捕获

Promise.all([
      new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log('A')
          reject(new Error('AAAAAAAAAAA'))
        }, 5000)
      }),
      new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log('B')
          reject(new Error('BBBBBBBBBBB'))
        }, 2000)
      }).catch(e => {
        return e
      })
    ]).then(result => {
      console.log(result)
    }).catch(e => {
      console.log(e)
    })
  }

----------------------------------------------
控制台先后输出:
B            //2s后输出B
A            //5s后输出A
AAAAAAAAAAA            //A输出后立即输出错误'AAAAAAAAAAA'

 上面代码中为什么Promise. all最后捕获的是错误'AAAAAAAAAAA'而不是‘BBBBBBBBBBB’。因为在第二个Promise实例中,2秒后虽然状态变为Rejected并且抛出了Error,但是被自身之后的catch方法捕获了该错误且return。之前已经知道,Promise之后的then和catch方法其实返回的是一个新的Promise实例,若方法中没有抛出新的错误,其后续的状态就会变为Resolved。而第一个实例抛出错误后,并未被后续方法捕获,最后状态为Rejected,错误最终被外层Promise. all方法的后续catch所捕获,最后输出'AAAAAAAAAAA'。

Promis.race()

与上面方法一样,同样将多个Promise实例包装成一个新的Promise实例。

Promise.race([P1,P2,P3])
    .then( value => { /*do something*/ } )
    .catch(e => { /*do something*/ })

Promise实例组中,P1、P2、P3谁的状态先发生变化(Resolved 或 Rejected),Promise.race()状态也发生改变,P1(or P2 or P3)的返回值传递给Promise.race()回调函数。

Promise.resolve()

将一个对象转为一个Promise对象,以下几种情况

let p = new Promise( (resolve,reject) => { resolve(1)} )
//传入Promise对象p,返回还是p
Promise.resolve(p)

//传入一个非thenable对象(thenable对象,就是一个对象具有then方法,下面会说明),或者非对象
Promise.resolve('_JayKoo')
--------------------------------------
//上面代码等同于
new Promise( (resolve,reject) =>{
    resolve('_JayKoo');
})

//thenable对象,具有then方法的对象
//then方法满足以下格式
let obj = {
    then(res , rej){     //then函数,参数满足Promise回调函数中的参数格式。then函数,相当于,Promise构造函数中的回调函数格式。
        if(/*Resolved*/){ res(value) }
        else { rej(error) }
    }
}

//将obj转为Promise对象,且立即调用then方法
Promise.resolve( obj )
---------------------------------------------------------------------------
//以上代码的效果等同于立即执行了
new Promise( (res, rej) => {
    /*obj对象中的操作*/
    if(/*Resolved*/){ res(value) }
    else { rej(error) }
})

//不带参数,立即生成一个Promise对象
//Promise.resolve()方法的执行,是在本轮注册的所有同步脚本事件的结束时(非异步)
let p = Promise.resolve()

Promise.reject()

Promise.reject()同样返回Promise对象.。

在Promise.resolve()中,传入的参数由thenable对象和非thenable对象两种情况,且之后的参数调用情况也不同。

但在Promise.reject()中,所有传参都会被当做Error抛出。

let p = Promise.reject(thenable)
--------------------------------------
//等同于
let p = new Promise( (resolve,reject) => {
    //即使是个thenable对象,也会原封不动地将这个对象当做错误信息抛出
    reject(thenable)
})
--------------------------------------
p.catch( e => {
   console.log( e === thenable) 
})
//true
原文地址:https://www.cnblogs.com/jaykoo/p/10007910.html