ES6中的Promise的用法总结

第一部分、什么是Promise ? 

Promise是ES6中提供的一个异步编程的解决方案,Promise本身是一个构造函数

 

typeof Promise  //  function

 

一般情况下 我们在开发中会使用 new Promise() 调用构造函数,创建一个新的Promise对象, Promise对象有两个特点

1、对象的状态不受外界影响。Promise对象是一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。

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

2、一旦Promise状态改变,就不会再有变化,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled 或者 从pending变为rejected。只要这两种情况发生,状态就不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的

使用Promise的好处,就是在处理异步程序时,将异步操作队列化,按照期望的顺序执行,返回符合预期的结果,这样即使是多重异步操作,也可以方便的使用Promise进行链式调用

3、Promise也有一些缺点。

首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

第二部分、循序渐进的介绍Promise的用法

1、最简单的用法

 

const  p =  new Promise((resolve, reject) => {
    // 在这里执行一个异步操作吧
    setTimeout(function(){
        console.log(1234)
        resolve(1234)
    }, 3000)
})

// 创建这个Promise之后, 3秒后 会控制台输出1234,并且3秒后得到了一个结果,异步程序返回了1234这个结果,那么

p.then((res) => {
    console.log(res)
})

// 控制台会输出1234 ,promise的then方法 会再次返回一个promise,不过值默认undefined

p.then((res) => {
    console.log(res)
}).then((res)=>{
   console.log(res)    
})

// 1234, undefined

 

2、reject的用法

 

const p2 = new Promise((resolve, reject)=>{
    // 执行一个异步操作
    setTimeout(function(){
        console.log(1024)
        reject(1024)
    }, 3000)
})

p2.then(res=>{
    console.log(res)
}).catch(res=>{
    console.error(res)    
})

//  3秒之后 输出错误 1024

 

3、all的用法, 多个异步操作进行数组形式的返回值处理,当所有的异步都resolve时,可以执行then操作,当其中一个或多个reject时,所有的异步都会停止调用,直接返回最早发生错误的那个结果

 

const pa = new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pa')
        resolve('pa')
    },3000)
})

const pb = new Promise((resolve, reject)=>{
   setTimeout(function(){
        console.log('pb')
        resolve('pb')
    },4000)
})

const pc = new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pc')
        resolve('pc')
    },5000)
})

const pd =  new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pd')
        reject('pd')
    },5000)
})


Promise.all([pa, pb, pc]).then((res)=>{
     console.log('成功' + res)
})

// 3秒后 pa  4秒后pb 5秒后 pc pd 然后输出成功pa,pb,pc

Promise.all([pa, pb, pd]).then((res)=>{
    console.log('成功' + res)
}).catch(err=>{
    console.log('失败' + err)
})

// 输出失败pd

 

4、race的用法, 语法和all()一样,但是返回值有所不同,race根据传入的多个Promise实例,只要有一个实例resolve或者reject,就只返回该结果,其他实例不再执行,也就是说多个异步程序,只返回响应最快的那个异步程序,不论成功或者失败,就把最快响应的返回值返回,后面的异步程序不再执行

 

const pa = new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pa')
        resolve('pa')
    },3000)
})

const pb = new Promise((resolve, reject)=>{
   setTimeout(function(){
        console.log('pb')
        resolve('pb')
    },4000)
})

const pc = new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pc')
        resolve('pc')
    },5000)
})

const pd =  new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pd')
        reject('pd')
    },5000)
})

const pe =  new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pe')
        reject('pe')
    },2000)
})

const pf =  new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pf')
        resolve('pf')
    },2000)
})

Promise.race([pa, pe, pf]).then(res=>{
    console.log('成功' + res)
}).catch(res=>{
    console.log('失败' + res)
})


Promise.race([pd, pe]).then().catch(res=>{
    console.log('失败' + res)
})

// 2秒后 输出 失败 + pe 

// 2秒后 输出 失败 +  pe

 

5、resolve方法,

Promise的resolve方法,用于将非Promise类型的对象,转为Promise对象,这样就可以调用Promise原型对象上的方法了

 

Promise.resolve(x) 

上面的写法等价于 

new Promise(resolve => { resolve(x)})

 

resolve的参数分为几种不同的情况:

(1)没有参数,如果没有参数,这直接返回一个resolved状态的Promise对象 

const p = Promise.resolve()

相当于 

const p = new Promise(resolve => {
    resolve undefined
})

p.then(res=>{
    console.log(res)
})

// 输出 undefined

(2) 参数是一个不具有then方法的对象,或者是一个基数数据类型的值,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved,值为指定值

const p = Promise.resolve('pro')

p.then((x) =>{
    console.log(x)
})

// 输出 'pro'

 

(3) 参数是一个具有then方法的对象,Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

const obj = {
    then: function(resolve, reject) {
        resolve(100)
    }
}

const p  = Promise.resolve(obj)

p.then((res) => {
    console.log(res)
})

// 输出 100

 

(4)参数是一个Promise对象,那么将原封不动的返回这个Promise对象

 

6、reject方法

reject与resolve方法基本类似,但是要注意一种情况,就是当参数是一个thenable对象时

const thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})

// true

7、finally方法,finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。finally本质上是then方法的特例。

const  p = new Promise((resolve, reject)=>{
    const a = Math.ceil( Math.random() * 10 )
    setTimeout(function(){
        if(a > 5) {
            resolve(a)
        } else {
            reject(a)
        }
    },3000)
})


p.then(res=>{
    console.log(res)
}).catch(err=>{
    console.error(err)    
}).finally(()=>{
   console.log('结束')
})

// 无论是resolve 还是 reject都会 执行 finally

// finally的 polyfill也很简单

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

 

posted @ 2019-08-28 19:04  曼施坦因  阅读(8241)  评论(0编辑  收藏  举报