概念
Promise是异步编程的一种解决方案
,比传统的解决方案——回调函数和事件——更合理和更强大。Promise 是异步编程的一种解决方案,主要用来解决回调地狱的问题,可以有效的减少回调嵌套
。真正解决需要配合async/await。
特点:
(1)对象的状态不受外界影响。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。
缺点:
(1)无法取消Promise,一旦新建它就会立即执行,无法中途取消。和一般的对象不一样,无需调用。
(2)如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
(3)当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
代码体验
抽奖功能
代码:
<body>
<div><button id="btn">点击抽奖</button></div>
<script>
//生成随机数
function rand(m, n) {
return Math.ceil(Math.random() * (n - m + 1)) + m - 1;
}
//获取元素对象
const btn = document.querySelector('#btn');
//绑定单击事件
btn.addEventListener('click', function () {
//定时器
// setTimeout(() => {
// let n = rand(1, 100);
// if (n <= 30) {
// alert('喜报~~~~奖品为 劳斯莱斯 一辆!');
// } else {
// alert('再接再厉');
// }
// }, 1000);
//promise形式实现,resolve解决(成功调用),reject拒绝(失败调用)(两个都是函数类型的数据)
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
let n = rand(1,100)
if(n<=70){
resolve()
}else{
reject()
}
},500)
})
console.log(p,"promise")
p.then(()=>{
alert('喜报~~~~奖品为 劳斯莱斯 一辆!'); //这个回调函数是成功的
},()=>{
alert('再接再厉');//这个回调函数是失败的
})
})
</script>
</body>
pormise基本流程
为什么要用promise?
1、链式调用,解决回调地狱问题
2、给promise对象绑定回调函数,可以再异步任务结束后指定多个
回调地狱怎么解决?
promise链式调用,用promise加上await和async关键字来实现异步传同步
如何使用Promise?
不属于new Promise的API(4个)
1、Promise.resolve方法:(value)=>{}
value:成功的数据或promise对象
说明:返回一个成功/失败的promise对象
2、Promise.reject方法:(reason)=>{}
reason:失败原因
说明:返回一个失败的promise对象
3、Promise.all方法:(promises)=>{}
promises:包含n个promise的数组
说明:返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就 直接失败
4、Promise.race方法:(promises)=>{}
promises:包含n个promise的数组
说明:返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态
自定义(手写)Promise
如何让状态只执行一次?
then方法执行回调
异步任务then方法实现
图一
图二
指定多个回调
同步任务then方法返回结果
异步任务then方法返回结果
整体封装好的代码
class Promise{
//构造方法
constructor(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//声明属性
this.callbacks = [];
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//调用成功的回调函数
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved(data);
});
});
}
//reject 函数
function reject(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//执行失败的回调
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected(data);
});
});
}
try{
//同步调用『执行器函数』
executor(resolve, reject);
}catch(e){
//修改 promise 对象状态为『失败』
reject(e);
}
}
//then 方法封装
then(onResolved,onRejected){
const self = this;
//判断回调函数参数
if(typeof onRejected !== 'function'){
onRejected = reason => {
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
//value => { return value};
}
return new Promise((resolve, reject) => {
//封装函数
function callback(type){
try{
//获取回调函数的执行结果
let result = type(self.PromiseResult);
//判断
if(result instanceof Promise){
//如果是 Promise 类型的对象
result.then(v => {
resolve(v);
}, r=>{
reject(r);
})
}else{
//结果的对象状态为『成功』
resolve(result);
}
}catch(e){
reject(e);
}
}
//调用回调函数 PromiseState
if(this.PromiseState === 'fulfilled'){
setTimeout(() => {
callback(onResolved);
});
}
if(this.PromiseState === 'rejected'){
setTimeout(() => {
callback(onRejected);
});
}
//判断 pending 状态
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved: function(){
callback(onResolved);
},
onRejected: function(){
callback(onRejected);
}
});
}
})
}
//catch 方法
catch(onRejected){
return this.then(undefined, onRejected);
}
//添加 resolve 方法
static resolve(value){
//返回promise对象
return new Promise((resolve, reject) => {
if(value instanceof Promise){
value.then(v=>{
resolve(v);
}, r=>{
reject(r);
})
}else{
//状态设置为成功
resolve(value);
}
});
}
//添加 reject 方法
static reject(reason){
return new Promise((resolve, reject)=>{
reject(reason);
});
}
//添加 all 方法
static all(promises){
//返回结果为promise对象
return new Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
//遍历
for(let i=0;i<promises.length;i++){
//
promises[i].then(v => {
//得知对象的状态是成功
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 存入到数组中
arr[i] = v;
//判断
if(count === promises.length){
//修改状态
resolve(arr);
}
}, r => {
reject(r);
});
}
});
}
//添加 race 方法
static race (promises){
return new Promise((resolve, reject) => {
for(let i=0;i<promises.length;i++){
promises[i].then(v => {
//修改返回对象的状态为 『成功』
resolve(v);
},r=>{
//修改返回对象的状态为 『失败』
reject(r);
})
}
});
}
}
async函数与await表达式
1、async
- 使用async函数的返回值为 Promise对象
- Promise对象的结果由async函数执行的返回值决定
async function main1() {
//1. 如果返回值是一个非Promise类型的数据 则状态为成功,返回一个成功的promise对象
return 521;
}
async function main2() {
//2. 如果返回的是一个Promise对象 则状态取决于返回结果
return new Promise((resolve, reject) => {
// resolve('OK'); //成功
reject("Error"); //失败
});
}
async function main3() {
// 3. 抛出异常 返回一个失败的promise对象
throw "出错啦";
}
let result1 = main1();
let result2 = main2();
let result3 = main3();
console.log(result1);
console.log(result2);
console.log(result3);
2、await 表达式
- await右侧表达式一般为promise对象,但也可以使其他的
- 如果表达式是promise对象,await返回的是promise成功的值
- 如果表达式是其他值,直接将此值作为await的返回值
- 注意
- await必须写在async函数中,但async函数中可以没有await
- 如果await的promise失败了,就会抛出异常,需要try...catch捕获处理
async function main() { let p = new Promise((resolve, reject) => { // resolve("OK"); reject("Error"); try { let res3 = await p; console.log(res3) } catch (e) { //catch捕获失败状态 console.log(e); } } main();