likes
comments
collection
share

学会五种获取Promise实例的方法即学会Promise!!!

作者站长头像
站长
· 阅读数 33

认识Promise

Promise实例具备的私有属性:

  • [[PromiseState]]: "pending":实例状态 "pending":准备(默认) "fulfilled":成功 "rejected":失败
  • [[PromiseResult]]: 实例值(结果) Promise.prototype提供一些供实例调用的公共属性方法[Promise实例.xxx()]:
  • then
  • catch
  • finally Promise本身为一个普通对象,拥有一些静态私有属性方法[Promise.xxx()]:
  • all
  • any
  • race
  • reject: Promise.reject(xxx)立即创建一个 状态为rejected失败,值是xxx 的promise实例
  • resolve: Promise.resolve(xxx)立即创建一个 状态为fulfilled成功,值是xxx 的promise实例

一:new Promise([executor])

let p = new Promise([executor]);

  • Promise只能被'new'执行,不能作为普通函数执行
  • [executor]必须是个函数,如果不是函数则报错
  • 而且new Promise的时候会把[executor]立即执行,并且Promise内部为[executor]传递两个实参,一般都基于resolve和reject两个形参来接收传递的实参信息
    • resolve([value]):把实例的状态改为fulfilled,值改为[value] 代表成功的结果
    • reject([reason]):把实例的状态改为rejected,值改为[reason] 代表失败的原因
  • [executor]函数中的代码,自上而下执行报错,也会修改实例的状态为rejected,值是报错原因

PS:一旦实例的状态从pending状态改为别的状态就不能再次修改为其他状态

let p = new Promise((resolve, reject) => {
        resolve('OK');
        reject('NO');//一旦实例的状态从pending状态改为别的状态就不能再次修改为其他状态
})
console.log(p);
/*输出:
  Promise {<fulfilled>: 'OK'}
    [[Prototype]]: Promise
    [[PromiseState]]"fulfilled" 
    [[PromiseResult]]"OK"
*/

二:Promise.reject()/Promise.resolve()

  • Promise.reject(xxx)立即创建一个 状态为rejected失败,值是xxx 的Promise实例
  • Promise.resolve(xxx)立即创建一个 状态为fulfilled成功,值是xxx 的Promise实例
Promise.resolve('OK') //创建了一个 状态为成功,值为'OK'的实例
Promise.reject('NO') //创建了一个 状态为成功,值为'NO'的实例

三:实例.then/catch/finally()返回一个全新的Promise实例

实例.then([onfulfilled],[onrejected])

  • [onfulfilled]方法会在promise实例状态为fulfilled的时候执行
  • [onrejected]方法会在promise实例状态为rejected的时候执行 他俩都会把实例的结果([[PromiseResult]])给两个函数

每次执行then方法都会返回一个全新的promise实例 (例如:p2)

  • 新实例的状态和值由上一个 '实例'.then 传递进来的[onfulfilled]/[onrejected]方法执行决定
    • 方法执行如果报错,则新实例p2状态就是失败,值就是报错的原因
    • 方法执行没有报错,则再看方法执行的返回值:
      • 如果返回结果是一个Promise实例[用@P表示]: 则@P的状态和值直接影响p2的状态和值
      • 如果返回的不是promise实例: 则p2的状态是fulfilled,值是return返回的值(如果没有返回值,则promise实例的值是undefined)
let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(100);
    }, 1000)
});
let p2 = p1.then(
    value => {
        console.log('成功', value); //'成功' 100
        return Promise.resolve(value * 10); //@P
    },
    reason => {
        console.log('失败', reason);
        return Promise.reject(value * 20); //@P
    }
);
p2.then(
    value => {
        console.log('成功', value); // '成功' 1000
    },
    reason => {
        console.log('失败', reason);
    }
).then(
    value => {
        console.log('成功', value);// '成功' undefined
    },
    reason => {
        console.log('失败', reason);
    }
);
/*输出:
'成功' 100
'成功' 1000
'成功' undefined
*/

Promise之所这样设计(.then返回新的Promise实例),就是为了实现'THEN链' [实例.then().then()...]

  • 'THEN链'具备'穿透/顺延'机制,执行then方法的时候,[onfulfilled]或者[onrejected]可以不传,如果不传,则顺延到下一个等同状态的方法上!!!!!
Promise.reject(100)
    .then(
        /* value => {
            return value;
        },
        reason => {
            throw reason;
        } */
    ) //或者.then(null,null)
    .then(
        value => {
            console.log('成功', value);
        },
        null)
    .then(
        null,
        reason => {
            console.log('失败', reason); // 失败 100
        })
    .then(
        value => {
            console.log('成功', value); // 成功 undefined
        },
        reason => {
            console.log('失败', reason);
        })

实例.catch()

实例.catch([onrejected]):可以理解为 promise.then(null,[onrejected])

  • 真实项目中,一般都是then中只传递onfulfilled方法,在then链末尾加一个catch处理失败的事情,这样不论哪一级出现失败的实例都会顺延到最后的catch中;
  • 如果出现失败的Promise实例,而我们并没有基于catch等方法对其进行处理,则会在控制台抛红,虽然不影响代码的执行,但是身为程序员见红则心烦意乱...
Promise.resolve(100).then(value => {
    console.log('成功', value); //成功 100
    return Promise.reject(value / 10);
}).then(value => {
    console.log('成功', value);
    return value / 10;
}).then(value => {
    console.log('成功', value);
    return value / 10;
}).catch(reason => {
    console.log('失败', reason); //失败 10
})

实例.finally()

promise.finally([function]):不管是成功还是失败,都会执行

四:Promise.all/any/race([promises])返回一个全新的Promise实例

Promise.all/any/race([promises]):执行方法,传递一个包含零到多个promise实例的集合(promises),返回的结果是一个全新的Promise实例(用@P表示) 如果在promises集合中,某项并不是Promise实例,则会把其默认转换为状态为成功,值为本身值的实例

  • all: 集合中每一项都是成功,@P才是成功 (值: 和原始集合相同的顺序,记录每一项成功的结果),只要有一项是失败,则@P就是失败 (值: 当前失败项的值)并且不再往后处理
  • any: 集合中只要有一项是成功,@P就是成功 (值: 成功项的值)并且不再往后处理,只有都是失败的,@P才是失败 (AggregateError: All promises were rejected)
  • race: 集合中谁先确定成功或失败状态,则@P就以谁的结果为主(哪怕是失败的)
let p1 = Promise.resolve(1);
let p2 = Promise.reject(2);
let p3 = new Promise(resolve => {
    setTimeout(() => {
        resolve(3)
    }, 2000);
});
let p4 = new Promise(resolve => {
    setTimeout(() => {
        resolve(4)
    }, 1000);
});
let p5 = 5; // 转换为 Promise.resolve(5)

let p = Promise.all([p1, p2, p3, p4, p5])
p.then(values => {
    console.log('成功', values);
}, reasons => {
    console.log('失败', reasons); //失败 2
})

p = Promise.any([p1, p2, p3, p4, p5])
p.then(values => {
    console.log('成功', values); // 成功 1
}, reasons => {
    console.log('失败', reasons);
})

p = Promise.race([p1, p2, p3, p4, p5])
p.then(values => {
    console.log('成功', values); // 成功 1
}, reasons => {
    console.log('失败', reasons);
}) 

五:Promise+Generator的语法糖:async/await

async对函数进行修饰

  • 基于async修饰函数,函数默认的返回值会变为一个Promise实例
    • 如果函数执行报错,则返回状态为失败,值为报错原因的实例
    • 如果本身返回就是一个新的Promise实例,则以自己返回的为主
    • 剩下情况则返回状态为成功,值为return返回的值的实例
  • 想要在函数中使用await,那么函数必须经过async的修饰 await: let value = await [promise实例]
  • await后面必须跟一个promise实例,如果不是则默认转换为状态为成功,值为本身的实例
    • await 10 => Promise.resolve(10)
  • await会监听后面Promise实例的状态
    • 只有实例状态是fulfilled成功,才会把实例值赋值给value,并且当前上下文中await下面的代码才会继续执行[或者理解为: '等待'后面的实例是成功状态,代码才继续执行]
    • 如果实例状态是pending/rejected,则当前上下文中,await下面的代码不会执行,也不会给value赋值,只有状态为成功,才会把成功的结果赋值给value,下面代码才会执行
  • await异常处理: 如果后面的promise实例是失败,可用try catch的方法进行异常捕获,控制台就不会抛红

基于async修饰的函数,如果函数体中遇到await

  • 在await没有处理完之前默认返回 状态是pending值是undefined 的实例
  • 等待await处理结果
    • 如果await后面实例是失败的,则函数返回的实例也是失败的,值是失败原因
    • 如果await后面实例是成功的,则继续执行await下面的代码,而函数返回的实例的状态也要再进一步判断(因为async修饰的函数中可能含有多个await)... 如果整个过程中没有出现报错和失败的实例,则最后函数返回的实例状态是fulfilled,值是函数return的值 总结:async修饰函数的返回值是要依赖函数中await的处理!!

学会五种获取Promise实例的方法即学会Promise!!!