promise

一、Promise

1、什么是promise

抽象表达:
    1、Promise是一门新的技术(ES6规范)
    2、Promise是JS中进行异步编程的新解决方案
        备注:旧方案是单纯使用回调函数
具体表达:
	1、从语法上来说:Promise是一个构造函数
    2、从功能上来说:Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值
  • 具体表达
//1、实例化时,传递一个回调函数(执行器函数),同时也会执行
//2、传递的回调函数可以称其为执行器函数,执行器函数是同步执行的,为同步回调函数
//3、得到的p1是一个基于Promise的实例,该实例中拥有两个属性
	//     [[PromiseState]]: "pending"   指明了promise的状态
    //     [[PromiseResult]]: undefined  批明了promise的值
const p1=new Promise((resolve,reject)=>{
    setTimeout(()=>{
		//取当前时间UTC
        const time=Date.now();
//4、可以通过resolve以及reject改变promise的状态,以及值
        //判断是否能被2整除
        if(time%2){
//4.1、执行reject,将状态更改为失败:rejected,传入的参数就是[[PromiseResult]]属性值。
			//当为奇数时,将状态更改为成功,值为获得的数字time
            console.log('奇数',time);
            resolve(time);
        }else{
//4.1、执行resolve,将状态更改为成功:fulfilled,传入的参数就是[[PromiseResult]]属性值。
            //当为偶数时,将状态更改为失败,值为获得的数字time
            console.log('偶数',time)
            reject(time)
        }
    })
})
console.log(p1)
//5、p1实例的原型对象中有一个属性then,类型是一个函数。该函数可以接受两个回调函数
p1.then((value)=>{
    console.log('成功的回调',value)
},(reason)=>{
	console.log('失败的回调',reason)
})
  • then语法
//基本语法形式
p.then(onFulfilled[, onRejected]);
//参数介绍:
//p: promise的实例对象
        //onFulfilled:是Promise的成功情况下的回调函数
        //onRejected:是Promise的失败情况下的回调函数
p.then((value) => {
  // fulfillment	里面的参数为成功的值。类似(resolve(value))
    console.log(value);
}, (reason) => {
  // rejection  里面的参数为成功的值。类似(reject(reason))
    console.log(reason)
});

2、promise的状态改变

const p1=new Promise((resolve,reject)=>{
	resolve(1);//将状态更改为成功,值为1
    reject(2);//将状态更改为失败,值为2
})
console.log(p1);
//成功的结果数据一般称为value,对应的回调函数是onFulfillment
//失败的结果数据一般称为reason,对应的回调函数是onReject
p1.then((value)=>{
    console.log(value);
},(reason)=>{
    console.log(reason)
})
  • 注意
pending是初始状态
    1、pending变为fulfilled
    2、pending变为rejected
说明:只有这两种,且一个promise对象只能改变一次
	无论变为成功还是失败,都会有一个结果数据
	成功的结果数据一般为value,失败的结果数据一般称为reason
  • 一个promise对象只能改变一次的案例
const p1=new Promise((resolve,reject)=>{
	resolve(100);//将状态更改为成功,值为100
    reject(500);//不会执行到这一行代码
    //所以结果是
    //[[Prototype]]: Promise
    //[[PromiseState]]: "fulfilled"
    //[[PromiseResult]]: 100	
})

3、更改状态的三种方式

 // 1、通过resolve将状态更改为成功
    const p1 = new Promise((resolve,reject)=>{
        resolve(1);
    })
    // [[PromiseState]]: "fulfilled"
    // [[PromiseResult]]: 1
    console.log(p1);

    // 2、通过reject将状态更改为失败
    const p2 = new Promise((resolve,reject)=>{
        reject(2);
    })
    // [[PromiseState]]: "rejected"
    // [[PromiseResult]]: 2
    console.log(p2);

    // 3、异常,在执行器函数中,如果发生异常,状态为失败,值为异常信息
    const p3 = new Promise((resolve,reject)=>{
        const a = 1;
        a();
    })
    // [[PromiseState]]: "rejected"
    // [[PromiseResult]]: TypeError: a is not a func
    console.log(p3);

    // 手动抛出异常
    const p4 = new Promise((resolve,reject)=>{
         throw "发生异常啦"
    })
    // [[PromiseState]]: "rejected"
    // [[PromiseResult]]: 发生异常啦
    console.log("p4",p4);

4、promise的基本流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CbGKVVMZ-1629900977961)(C:\Users\12749\AppData\Roaming\Typora\typora-user-images\image-20210825195812110.png)]

    // 1、在实例化时,必须要传入回调函数(执行器函数),否则异常
    // const p1 = new Promise();
    // console.log(p1);

    // 2、传入了执行器函数,但是并没有更改状态,那么得到p2的状态为pending
    // const p2 = new Promise(function (){
    //
    // })
    // // [[PromiseState]]: "pending"
    // // [[PromiseResult]]: undefined
    // console.log(p2);

    // 3、执行器函数,可以执行同步也可以执行异步。
    // 执行同步
    // const p3 = new Promise(function (resolve,reject){
    //     let a = 1;
    //     let b = 2;
    //     resolve(1);// 状态成功,值为1
    // })
    // // [[PromiseState]]: "fulfilled"
    // // [[PromiseResult]]: 1
    // console.log(p3);

    // 执行异步
    // const p3 = new Promise(function (resolve,reject){
    //     setTimeout(()=>{
    //         let a = 1;
    //         let b = 2;
    //         resolve(1);// 状态成功,值为1
    //     })
    // })
    // // [[PromiseState]]: "fulfilled"
    // // [[PromiseResult]]: 1
    // console.log(p3);

    // 4、then函数,返回的是一个新的Promise实例
    const p4 = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            reject(200);
            resolve(100);
        })
    })
    const p5 = p4.then(function (value){
        console.log(value);
    },function (reason){
        console.log(reason);
    })
    console.log(p5)

二、为什么要使用Promise

1、指定回调函数的方式更加灵活

  • 旧的:必须在启动异步任务前指定
  • promise:启动异步任务=>返回promise对象 =>给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)
//1、回调函数:必须在启动异步任务前指定(调用函数时,必须要传入一个回调函数)
const fn=(cb)=>{
    setTimeout(()=>{
        let a=100;
        cb(a);
    },1000)
}
//调用之前,指定回调函数
fn((num)=>{
    console.log(num)
});

//2、启动异步任务
new Promise(()=>{
    setTimeout(()=>{
		let a=100;
        console.log(a)
    },1000)
})

//3、启动异步任务=>返回promise对象
const p1=new Promise(()=>{
    setTimeout(()=>{
		let b=100;
        console.log(b);
    })
})
console.log(p1);//p1是一个promise对象

//4、启动异步任务 => 返回promise对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)
const p1=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        let c=200;
        reject(c)
    },1000)
})
//可以在异步任务结束后指定/多个
p1.then(value=>{
    console.log('1',value);//100
},reason=>{
    console.error('1',reason);//200
})

p1.then(value=>{
    console.log('2',value);//100
},reason=>{
    console.error('2',reason);//200
})

p1.then(value=>{
	console.log('3',value);//100
},reason=>{
    console.error('3',reason);//200
})

2、支持链式调用,可以解决回调地狱问题

  • 什么是回调函数?

回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件

  • 回调地狱的缺点?

不便于阅读

不便于异常处理

  • 解决方案?

promise链式调用

  • 终极解决方案?

async / await

三、如何使用Promise

1、API

  • ①、Promise构造函数:Promise (excutor){ }

(1)、executor函数:执行器(resolve,reject)=>{}

(2)、resolve函数:内部定义成功时我们调用的函数 value=>{ }

(3)、reject函数:内部定义失败时我们调用的函数 reason=>{ }

说明:executor会在Promise内部立即同步调用,异步操作在执行器中执行

//执行器函数会被 立即调用
const p1=new Promise((resolve,reject)=>{
    console.log(1);
    setTimeout(()=>{
		//此函数为executor函数
        resolve(100);//状态为成功,值为100
    })
})
console.log(p1)
console.log(2)
输出结果
// 1
//Promise {<pending>}
//[[Prototype]]: Promise
//[[PromiseState]]: "fulfilled"
//[[PromiseResult]]: 100
//2
  • ②、Promise.prototype.then方法:(onResolved,onRejected)=>{}

(1)、onResolved函数:成功的回调函数(value)=>{ }

(2)、onRejected函数:失败的回调函数(reason)=>{ }

说明:指定用于得到成功value的成功回调和用于得到失败reason的失败的回调

返回一个新的promise对象

//then 函数是在原型对象当中
const p1 =new Promise((resolve,reject)=>{
	resolve(100);//成功,值为100	
})

const p2=p1.then((value)=>{
	//当状态为成功时,执行成功回调函数,接收的参数为成功的值。这是onResolve函数
    console.log(value)
},(reason)=>{
    //当状态为失败时,执行失败的回调函数,接收的参数为失败的值。这是onRejected函数
    console.log(reason);
});
console.log(p2);  //这是一个新的promise
  • ③、Promise.prototype.catch方法: (onRejected) => {}

(1) onRejected函数: 失败的回调函数 (reason) => {}

说明: then()的语法糖, 相当于: then(undefined, onRejected)

// 1、如果状态为失败,必须要对失败的内容进行处理,否则异常:Uncaught (in promise) 100
// const p1 = new Promise(function (resolve,reject){
//     reject(100);// 状态为失败,值为100
// })

// 2、处理异常方案一
// const p1 = new Promise(function (resolve,reject){
//     reject(100);// 状态为失败,值为100
// })
// p1.then(undefined,function (reason){
//     console.log(reason);
// })

// 3、处理异常方案二
// const p1 = new Promise(function (resolve,reject){
//     reject(100);// 状态为失败,值为100
// })
// // catch传递的是一个失败的回调函数,可以认为是then(undefined, onRejected)
// p1.catch(reason => {
//     console.log(reason);
// })

// 4、如果使用then当中的失败回调,也使用catch会怎样。
const p1 = new Promise(function (resolve,reject){
  reject(100);// 状态为失败,值为100
})
// 如果then函数中没有指定失败回调,那么会执行catch当中的失败回调。如果catch没有失败回调报异常。
// p1.then(undefined).catch(reason=>{
//     console.log(reason)
// });

// 如果then函数中指定了失败回调,那么不会执行catch当中的失败回调
p1.then(undefined,reason=>{
  console.log("then",reason);
}).catch(reason=>{
  console.log("catch",reason);
})
  • ④、Promise.resolve方法:(value)=>{}

(1) value: 成功的数据或promise对象

说明: 返回一个成功/失败的promise对象

// 1、未传入参数,得到的p1是一个promise.状态为成功fulfilled,值为undefined.
// const p1 = Promise.resolve();
// console.log(p1);

// 2、传入一个非promise的数据,状态为成功fullfilled,值为传入的内容。
// const p2 = Promise.resolve({a:1});
// console.log(p2); //{a:1}

// 3、传入一个成功状态的promise:得到的是一个成功状态,值为200的promise
//    得到的p4是一个promise,该promise的状态以及值与p3相同。
// const p3 = new Promise((resolve,reject)=>{
//     resolve(200);
// })
// const p4 = Promise.resolve(p3);
// console.log(p4===p3);// true

// 4、传入的是一个失败的promise,那么得到的p6即是该promise
const p5 = new Promise((resolve,reject)=>{
reject(100);
})
const p6 = Promise.resolve(p5);
console.log(p6===p5);// true
  • ⑤、Promise.reject方法: (reason) => {}

(1) reason: 失败的原因

说明: 返回一个失败的promise对象

// 不管传入的是什么,得到的都失败的promise。传入的内容即是promise失败的值。
// 1、失败,值为undefined
// const p1 = Promise.reject();
// console.log(p1);

// 2、传入一个非promise,失败状态,值为2
// const p2 = Promise.reject(2);
// p2.catch(reason=>{
//     console.log(reason)
// })

// 3、传入成功的promise,p4是状态为失败,值是一个promise(p3)
// const p3 = Promise.resolve(2);
// const p4 = Promise.reject(p3);
// // console.log(p4);
// p4.catch(reason=>{
//     console.log(reason===p3);// true
// })

// 4、传入一个失败的promise,得到的状态为失败,值为该失败promise
const p5 = Promise.reject(2);// 失败的promise,值为2
const p6 = Promise.reject(p5);
// console.log(p6);
p6.catch(reason=>{
console.log(reason===p5);// true
})
  • ⑥、Promise.all方法: ([promises]) => {}

(1) promises: 包含n个promise的数组

说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败(同步情况下)

 const p1 = new Promise(function (resolve){
     setTimeout(function (){
         resolve(1);
     },100)
 })
 const p2 = new Promise(function (resolve,reject){
     setTimeout(function (){
         reject(2);
     },200)
 })
 const p3 = new Promise(function (resolve){
     setTimeout(function (){
         resolve(3);
     },300)
 })
 const p4 = Promise.resolve(4);
 // all方法返回的是一个promise,传入的是一个数组。数组的元素建议为promise.
 // 状态:如果数组中的元素都是成功的promise,那么状态为成功。如果传入的数组元素有失败的promise,那么状态为失败
 // 值:是一个数组,数组为所有成功promise的成功值。如果状态失败,那么值为失败的值。
 const p5 = Promise.all([p1,p2,p3,p4,100]);
 console.log(p5);
 p5.then(value=>{
     console.log(value);
 }).catch(reason=>{
     console.log("失败",reason);
 })
  • ⑦、Promise.race方法: (promises) => {}

(1) promises: 包含n个promise的数组

说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态

2、Promise的几个关键问题

  • ①、如何改变promise的状态?

(1)、resolve(value):如果当前是pending就会变为resolved

(2)、reject(reason):如果当前是pending就会变为rejected

(3)、抛出异常:如果当前是pending就会变为rejected

 // (1) resolve(value): 如果当前是pending就会变为resolved
 // const p1 = new Promise((resolve,reject)=>{
 //     resolve(100);// 将状态更改为成功,值为100
 // })
 // console.log(p1);

 // (2) reject(reason): 如果当前是pending就会变为rejected
 // const p1 = new Promise(function (resolve,reject){
 //     reject(100);// 将状态更改为失败,值为100
 // })
 // console.log(p1);

 // (3) 抛出异常: 如果当前是pending就会变为rejected
 const p1 = new Promise(function (resolve,reject){
     throw "异常"
 })
 console.log(p1);
  • ②、一个promise指定多个成功/失败回调函数,都会调用吗?

当promise改变为对应状态时都会调用

const p1 = new Promise(function (resolve,reject){
     reject(100);
 })
 p1.then(value=>{
     console.log(value);
 },reason=>{
     console.log(reason);
 })
 p1.then(value=>{
     console.log(value);
 },reason=>{
     console.log(reason);
 })
 p1.then(value=>{
     console.log(value);
 },reason=>{
     console.log(reason);
 })
 p1.then(value=>{
     console.log(value);
 },reason=>{
     console.log(reason);
 })
  • ③、改变promise状态和指定回调函数谁先谁后?

(1)、都有可能,正常情况下是先指定回调在改变状态,但也可以先改变状态在指定回调

(2)、如何先改状态在指定回调?

​ Ⅰ、在执行器中直接调用resolve() / reject()

​ Ⅱ、延迟更长时间才能调用then()

(3)、什么时候才能得到数据?

​ 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据

​ 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据

 // (1) 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
 // 正常情况下,执行器函数中是异步的行为。
 // const p1 = new Promise(function(resolve,reject){
 //     setTimeout(()=>{
 //         resolve(100);
 //     },1000)
 // })
 // p1.then(function (value){
 //     console.log(value);
 // })

 // (2) 如何先改状态再指定回调?
 // ① 在执行器中直接调用resolve()/reject()
 // const p1 = new Promise(function (resolve,reject){
 //     resolve(200);
 // })
 // p1.then(value=>{
 //     console.log(value);// 200
 // })

 // ② 延迟更长时间才调用then()
 // const p1 = new Promise(function (resolve,reject){
 //     setTimeout(()=>{
 //         resolve(300);
 //     },1000)
 // })
 // setTimeout(()=>{
 //     p1.then(value=>{
 //         console.log(value);
 //     })
 // },2000)

 // (3) 什么时候才能得到数据?
 // ① 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
 // const p1 = new Promise(function (resolve,reject){
 //     setTimeout(()=>{
 //         resolve(80);
 //     },1000)
 // })
 // p1.then(value=>{
 //     console.log(value);// 80
 // })
 // ② 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
 const p1 = new Promise(function (resolve,reject){
     resolve(80);
 })
 // 在then方法中会判断当前的状态如果已经发生改变,那么会立即调用对应的回调函数。
 p1.then(value=>{
     console.log(value);// 80
 })
  • ④、promise.then()返回的新prommise的结果状态由什么决定

(1)、简单表达:由then()指定的回调函数执行的结果决定

(2)、详细表达:

​ 如果抛出异常,新的promise变为rejected,reason为抛出的异常

​ 如果返回的是非promise的任意值,新promise变成resolved,value为返回的值

​ 如果返回的是另一个新promise,此promise的结果就会称为新promise的结果

 // const p1 = new Promise(function (resolve,reject){
 //     resolve(1);// 状态为成功,值为1
 // })
 // // p2的状态与值,由谁决定?答:由回调函数的返回值决定。
 // const p2 = p1.then(value=>{
 //     console.log(value);// 1
 // })
 // console.log(p2);




 const p1 = new Promise(function (resolve,reject){
     resolve(1);// 状态为成功,值为1
 })
 // 1、如果抛出异常, 新promise(p2)变为rejected, reason为抛出的异常
 // const p2 = p1.then(value=>{
 //     throw "异常"
 // })
 // console.log(p2);
 // p2.catch(reason=>{
 //     console.log(reason);
 // })

 // 2、如果返回的是非promise的任意值, 新promise变为resolved, value为返回的值
 // const p3 = p1.then(value=>{
 //     return 100;
 // })
 // console.log(p3);// 是一个状态为成功,值为100的 promise

 // 3、如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果
 // const p4 = p1.then(value=>{
 //     // 返回的是一个成功的promise.得到的p4为成功,值为100的promise
 //     // return Promise.resolve(100);
 //
 //     // 返回的是一个失败的promise,得到的p4为失败,值为200
 //     return Promise.reject(200);
 // })
 // console.log(p4);

 // 4、then函数得到的是一个新promise
 const p = Promise.resolve(50);
 const p5 = p1.then(value=>{
     return p;
 })
 console.log(p5 === p);// false
  • ⑤、promise如何串联多个操作任务?

(1)、promise的then()返回一个新的promise,可以形成then()的链式调用

(2)、通过then的链式调用串连多个同步/异步任务

  • ⑥、promise异常穿透?

(1)、当使用promise的then链式调用时,可以在最后指定失败的回调

(2)、前面任何操作出了异常,都会传到最后失败的回调中处理

  • ⑦、中断promise链?

(1)、当使用promise的then链式调用时,在中间中断,不在调用后面的回调函数

(2)、办法:在回调函数中返回一个pending状态的promise对象

新promise的结果

 // const p4 = p1.then(value=>{
 //     // 返回的是一个成功的promise.得到的p4为成功,值为100的promise
 //     // return Promise.resolve(100);
 //
 //     // 返回的是一个失败的promise,得到的p4为失败,值为200
 //     return Promise.reject(200);
 // })
 // console.log(p4);

 // 4、then函数得到的是一个新promise
 const p = Promise.resolve(50);
 const p5 = p1.then(value=>{
     return p;
 })
 console.log(p5 === p);// false
  • ⑤、promise如何串联多个操作任务?

(1)、promise的then()返回一个新的promise,可以形成then()的链式调用

(2)、通过then的链式调用串连多个同步/异步任务

  • ⑥、promise异常穿透?

(1)、当使用promise的then链式调用时,可以在最后指定失败的回调

(2)、前面任何操作出了异常,都会传到最后失败的回调中处理

  • ⑦、中断promise链?

(1)、当使用promise的then链式调用时,在中间中断,不在调用后面的回调函数

(2)、办法:在回调函数中返回一个pending状态的promise对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值