Promise全解析

  • A+
所属分类:js vue 前端

Promise是一个JS的异步编程解决方案,解决了传统异步编程回调地狱的问题。

Promise有三种状态:

  • pending(进行中) 

  • fulfilled(已完成)

  • rejected(已失败)

只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

其中pending 为初始状态,状态的变化只有两种:

  1. pending --- fulfilled(异步完成)

  2. pending --- rejected(异步失败)

且一旦状态改变,状态就会凝固,不会在变化了,这就导致了 Promise 一旦建立就会立即执行,无法取消。


Promise 的基本用法

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

Promise全解析

const promise = new Promise(function(resolve,reject){    // 异步操作
    if(success){    //异步操作成功        resolve(value);
    } else{         //异步操作失败        reject(err);
    }
})

Promise全解析

Promise 构造函数接收的参数是一个函数,改函数有两个有JS引擎指定的函数: resolve 函数 和 reject函数

  • resolve 函数有两个作用:

  1. 将 Promise 状态由 pending -- fulfilled (等待态 -- 成功态)

  2. 将异步操作成功的结果value 作为参数传递出去  (由后面讲的 then 方法接收)

  • reject 函数有两个作用:

  1. 将Promise 状态 pending -- rejected (等待态 -- 失败态)

  2. 将异步操作失败的错误信息 err 作为参数传递出去。 (由后面讲到的then / catch 方法接收)


Promise 的三个实例方法 then catch finally

  • 1、Promise.prototype.then()

Promise 实例具有 then方法,也就是说then方法是定义在原型对象上的。

Promise 实例生成后,可以用then方法分别指定 resolve状态和rejected状态的回调函数:获取Promise 内部的异步操作状态。

promise.then({    function(value){ console.log(value) },  //异步操作成功时(fulfilled态)调用
    function(err){ console.log(err) }       //异步操作失败时(rejected态)调用})

then 方法可以接收两个回调函数作为参数:

  1. 第一个回调函数在Promise 实例变成 fulfilled 时调用,并获取 resolve 函数传递的参数 value

  2. 第二个回调函数在Promise 实例变成rejected时调用,并获取 reject 函数传递的参数 err

then 方法的返回值是一个新的promise 对象,因此可以 .then 可以链式调用。

 

  •  2、Promise.prototype.catch()

Promise 实例的 catch 方法用于指定发生错误时的回调函数,是 .then(null,rejection)的语法糖。

promise.then(function(val){
    console.log(val)    //异步操成功败时(rejected态)调用}).catch(function(err){
    console.log(err)    //异步操作失败时(rejected态)调用})

上面代码中,如果 Promise 对象状态变为 fulfilled,则会调用then方法指定的回调函数;

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

另外,then方法指定的回调函数,如果运行抛出错误,也会被catch 方法捕获。

promise.then(val => console.log("fulfilled:",val))
       .catch(err => console.log("rejected:",err))// 等价于promise.then(val => console.log("fulfilled:",val))
       .then(null,err => console.log("rejected:",err))

如果 Promise 状态已经变成resolved , 再抛出错误时无效的,因为 Promise 的状态一旦改变,就永久保持该状态,不会在变了。

Promise 对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止,也就是说错误总会被下一个catch 语句捕获。

 

  • 3、Promise.prototype.finally()

Promise 实例的 finally 方法用于指定不管状态最终如何,都会执行的函数。是 .then(function,function)(function相同)的语法糖。

Promise全解析

promise.finally(message => console.log("状态变化了",message))// 等价于promise.then(
    message => console.log("状态变化了",message),
    message => console.log("状态变化了",message)
)// 无论成功还是失败都会执行

Promise全解析

 


 

Promise 的两个静态方法 all 和 race

Promise.all(arr) 方法是挂载在Promise构造函数的静态方法,它传入参数为一个Promise对象数组arr,返回值为一个Promise实例:

  1. 该实例会在Promise对象数组内所有对象的状态变为 fulfilled 时调用内部的 resolve函数;

  2. 该实例在Promise对象数组内任意对象的状态变为rejected时调用 reject函数(reject 函数的参数为第一个错误的promise 对象的err)

有点类似于js里的与操作(&&): 所有表达式为真时返回真,任意表达式为假时返回假。

Promise全解析

let p1 = new Promise((resolve,reject)=>{
    resolve('p1-success'),
})
let p2 = new Promise((resolve,reject)=>{
    resolve('p2-success'),
})
let p3 = new Promise((resolve,reject)=>{
    reject('p1-error'),
})

Promise.all([p1,p2,p3]).then(val=>{
    console.log(val)
}).catch(err=>{
    console.log(err)
})//输出 p1-error

Promise全解析

注意:Promise.all() 获得的成功结果的数组里面的数据顺序和 Promise.all() 接收到的数组顺序是一致的。即p1结果在前,即便p1的结果获取比p2要晚,这带来了一个绝大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用 Promise.all() 毫无疑问可以解决这个问题。

 

Promise.race()

Promise.race(arr) 方法返回一个 promise实例,一旦arr中的某个promise对象解决或拒绝,返回的 promise就会解决或拒绝。
顾名思义,Promise.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

Promise全解析

let p1 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p1-success')
    },1000)
})
let p2 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p2-success')
    },500)
})
let p3 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        reject('p3-error')
    },1000)
    
})

Promise.race([p1,p2,p3]).then(val=>{
    console.log(val)
}).catch(err=>{
    console.log(err)
})//输出 p2-success

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: