Promise

125 阅读3分钟

Promise 是ES6中新增的一个内置类,可以有效的处理异步编程。

传统在实现异步操作,并且是串行的模式下,基本上都是回调函数套回调函数,而Promise正好解决这个‘回调地狱’的问题

下面我们正式开始理解promise:

我们创建一个promise的实例
let p1 = new Promise([executor]);
- Promise是一个内置类
- p1是类的一个实例
- executor是传递的回调函数,并且这个回调函数必须传递不然会报错  
let p1 = new Promise(); //Uncaught TypeError: Promise resolver undefined is not a function

Promise本身是同步的(为了管理异步编程)

  • new Promise的时候会立即把executor函数执行
    • 在执行executor函数时传递两个参数分别是:resolve、reject,并且这两个参数都是函数
  • 创造了一个promise类的一个实例p1,并且会返回当前promise实例的状态和值
    • p1.__proto__中则存放着原型中的内置方法:catch、then等
[[PromiseState]]promie状态:pending准备状态  fulfilled/resolved成功  rejected失败
[[PromiseResult]]promise值:默认是undefined,一般存储成功的结果或者失败的原因

  • 在实例中执行resolve函数时会控制实例的状态变为成功,传递的值就是成功的结果
  • 执行reject时会控制实例状态变为失败,如果executor中函数执行报错,状态也会变成失败态,并且[[PromiseResult]]中是失败的原因。
let p1 = new Promise((resolve,reject)=>{
	resolve(100);//此时实例状态已经改变,下面再执行reject便不会再改变
    	reject(0);
)
then
  • then([A],[B]):基于then方法存放两个回调函数A/B,当promise状态成功则执行A,失败则执行B,并且把[[PromiseResult]]的值传递给对应的函数
  • then的存在是为了把当前实例成功或者是失败的结果存储下来,并且返回一个新的promise实例p2
    • p2的状态由上一个实例p1基于then存放的A/B来决定
      • 无论是函数A还是B执行,只要上一个实例执行不报错则p2的状态都是成功,反之执行报错就是失败
      • p2的值为A/B执行的返回值,或者是报错的原因
    • 如果A/B返回的是一个新的promise实例,则返回的promise实例的成功失败以及结果,直接决定p2的状态和结果
let p1 = new Promise((resolve, reject) => {
    // 管理一个异步操作:根据需求控制promise成功还是失败
    setTimeout(() => {
        let ran = Math.random();//获取0-1之间随机值
        ran < 0.5 ? reject('NO') : resolve('OK');
    }, 1000);
});
let p2 = p1.then(result => {
	//当p1实例的状态修改为成功时,通知第一个函数执行
    console.log(`成功了  ${result}`);
    return result;
}, reason => {
	//当p1实例的状态修改为失败的时候,通知第二个函数执行
    console.log(`失败了  ${reason}`);
    return reason;
});

  • 只要p2执行不报错,那么p2再执行then方法返回的实例状态就一定是成功
let p1 = new Promise((resolve, reject) => {
    reject('NO');
});
let p2 = p1.then(result => {
    console.log('成功->', result);
    return 10;
}, reason => {
    console.log('失败->', reason); //->失败 'NO'
    return 20;
});

let p3 = p2.then(result => {
    console.log('成功->', result); //->成功 20
}, reason => {
    console.log('失败->', reason);
});

catch

如果说then是处理成功的 catch则是处理失败做什么,一般会写在最后面

Promise.resolve(10).then(result => {
    console.log(`成功了 -> ${result}`);
    return result * a;
}).then(result => {
    console.log(`成功了 -> ${result}`);
    return result * a;
}).catch(reason => {
    console.log(`失败了 -> ${reason}`);
});
成功了 -> 10
失败了 -> ReferenceError: a is not defined
all

Promise.all:若同时处理多个Promise实例,那么等待所有promise实例都成功,返回的状态才是成功,只要有一个失败,整体状态就是失败

race

Promise.race:多个实例谁先处理完成,先处理完的状态不论是失败还是成功,就是最整体的状态

最后上一道面试题巩固一下,答案放后面了哦

new Promise((resolve, reject) => {
    reject(20);
}).then(result => {
    console.log(`成功了 -> ${result}`);
    return result * 10;
}, reason => {
    console.log(`失败了 -> ${reason}`);
    return reason / 10;
}).then(result => {
    console.log(`成功了 -> ${result}`);
    return Promise.reject(result * 10);
}, reason => {
    console.log(`失败了 -> ${reason}`);
    return reason / 10;
}).then(result => {
    console.log(`成功了 -> ${result}`);
    return result * 10;
}, reason => {																	       失败了 -> 20
    console.log(`失败了 -> ${reason}`);															成功了 -> 2
    return reason / 10;																	失败了 -> 20
});