0
点赞
收藏
分享

微信扫一扫

19、promise的理解和使用

Silence潇湘夜雨 2022-03-12 阅读 96

1.1、promise是什么?

(1)抽象表达

  • promise是一门新的技术(ES6规范)
  • promise是js进行异步编程新解决方案 备注:旧方案是单纯的函数回调

(2)具体表达

  • 从语法上来说:promise是一个构造函数
  • 从功能上来说:promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

1.2、为什么使用promise?

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

  • 旧的:必须在启动异步任务前指定
  • promise:启动异步任务=>返回promise对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)

(2)支持链式调用,可以解决回调地狱问题(面试经常问到)

  • 什么是地狱回调:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行条件
  • 回调地狱的缺点:不便于阅读;不便于异常处理。
  • 解决方案:promise链式调用

1.3、promise体验

    //生成一个随机数
    function rand(m,n){
        return Math.ceil(Math.random() * (n - m + 1)) + m - 1;
    };
//    获取元素对象
let eventbtn = document.querySelector("#btn");
//=给元素对象添加点击事件
    eventbtn.addEventListener('click',function (){
        //    普通方式
    //    添加定时器
    //     setTimeout(()=>{
    //     let n = rand(1,100);
    //         if (n<=30){
    //             alert("恭喜中奖")
    //         }else {
    //             alert('很遗憾,再接再厉')
    //         }
    //     },1000);
    //    promise方式实现-----promise是一个构造函数 可以对象实例化 promise的参数是一个函数,函数有两个形参resolve解决, reject拒绝
        let m = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                let n = rand(1,100);
                if (n<=30){
                    resolve() //将promise对象的状态设置为 成功
                }else {
                    reject() //将promise对象的状态设置为 失败
                }
            },1000);
        });
        m.then(()=>{
            alert("恭喜中奖")
        },()=>{
            alert('很遗憾,再接再厉')
        })
    });

1.4、使用promise封装fs读取文件

const fs require('fs')
//回调函数形式
fs.readFile('./resource/context.txt',(err.data)=>{
    //如果出错 则抛出错误
    if(err) throw err;
   //输出文件内容
    data.toString()
})
//promise形式
let m = new Promise((resolve, reject)=>{
            fs.readFile('./resource/context.txt',(err.data)=>{
                //如果出错 则抛出错误
                if(err) reject(err);
               //否则 输出文件内容
                resolve(data)
            })
});
//调用then方法 指定回调函数
m.then((value)=>{
    value.toString();
},(reason)=>{
    console.log(reason)
})

1.5、promise对象状态属性的介绍

1.5.1 实力状态中的一个属性 PromiseState

(1)三种状态 分别为 pending、resolved/fulfilled、rejected
(2)状态改变的时候只有两种可能,且一个promise对象只改变一次
修改promise对象状态的方法:
  • 由resolvet() 将pending=>resolved/fulfilled
  • 由reject() 将pending=>rejected
  • 抛出错误 如throw ‘出错了’

1.6、promise对象结果值属性介绍

1.6.1 promise对象的值

(1)实例对象中的另一个属性 PromiseResult;保存着异步任务 成功/失败 的结果
(2)可修改PromiseResult 值的有两个函数
  • resolved
  • rejected

1.7、promise工作流程

(1)先创建一个promise实例
(2)在promise对象中封装一些异步操作
(3)异步任务执行成功后,执行resolve(),resolve()回调则将promise对象状态设置为resolved;再调then()方法(指定回调函数的方法),调用第一个回调函数(参数),然后返回一个新的promise对象
(4)异步任务执行失败后,执行reject()函数,reject()将promise设置为rejected状态;再调用then()方法中的第二个回调函数,返回一个新的promise对象。

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

1.8、promise 的resolve()和reject()方法

(1)resolve()方法:(value)=>{};value 为成功的数据或者对象
说明:返回一个成功/或者失败的对象
(2)reject()方法:(reason)=>{} reason为失败的原因;
说明:返回一个失败的promise对象

1.9、改变promise状态和指定回调函数的先后顺序?

(1)都有可能,正常情况下是先指定回调函数再改变状态,但也可以先改变状态再指定回调函数。
(2)如何先改变状态再指定回调函数?
  • 在执行器中直接调用resolve()/reject()
  • 延迟更长时间再调用then()方法
(3)什么时候才能获取到数据?
  • 如果先指定回调函数,当状态发生改变时,回调函数就会调用,得到数据。
  • 如果先改变状态,那当指定回调函数,回调函数就会调用,得到数据。

1.10、promise如何串连多个操作任务?

(1)promise的then()返回一个新的promise,可以开成then的链式调用
			let p = new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve('ok')
                },1000)
            });
            p.then((value)=>{
                //返回一个promise对象
                return new Promise((resolve,reject)=>{
                    resolve('success')
                })
            }).then(value=>{
                console.log(value)// value 为 success
            }).then(value=>{
                console.log(value)//value 为undefined  因为上一个then()方法没有返回值
            })
(2)通过then()的链式调用串连多个同步/异步任务

1.11、关键问题 promise异常穿透?

(1)当使用promise的then链式调用时,可以在最后指定失败的回调
(2)前面任何操作出现了异常,都会传到最后失败的回调处理
			let p = new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve('ok')
                },1000)
            });
            p.then((value)=>{
                //console.log(value)
                throw '出错了'
            }).then(value=>{
                console.log(222)// value 为 success
            }).then(value=>{
                console.log(333)//value 为undefined  因为上一个then()方法没有返回值
            }).catch(reason=>{//直接穿过前面的两个then 执行catch
                console.log(reason)
            })

1.12、如何中断promise链?

(1)返回一个pending状态的promise对象
			let p = new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve('ok')
                },1000)
            });
            p.then((value)=>{
                return new Promise(()=>{})//返回pending状态 promise对象 解决中断promise链的唯一方法
            }).then(value=>{
                console.log(222)// value 为 success
            }).then(value=>{
                console.log(333)//value 为undefined  因为上一个then()方法没有返回值
            }).catch(reason=>{//直接穿过前面的两个then 执行catch
                console.log(reason)
            })

1.13、promise自定义封装

let p = new Promise((resolve,reject)=>{
        // resolve('ok')
        // reject('出错了');
        throw '出错' //抛出异常 改变promise状态 rejected
    });
    console.log(p)
      p.then(value=>{
            console.log("value==",value)
        },reason=>{
            console.log("reason==",reason)
      })
(1)初始结构搭建
//声明构造函数
function Promise(executor){//executor执行器参数

}
//添加then()方法
Promise.prototype.then = function (onResolved,onRejected){
    
}
    
(2)resolve和reject结构搭建
//声明构造函数
function Promise(executor){//executor执行器参数
    //resolve函数
    function resolve(data){
    };
    //reject函数
    function reject(data){
    }
    executor(resolve,reject);
}
//添加then()方法
Promise.prototype.then = function (onResolved,onRejected){

}
(3)resolve和reject代码实现
//声明构造函数
function Promise(executor){//executor执行器参数
    //最开始的promise状态
    this.PromiseState = 'pending'
    //最开始的promise值
    this.PromiseResult = null;
    //保存promise实例对象的this值
    const that = this;
    //resolve函数
    function resolve(data){
        //判断状态是否为pending
        if(that.PromiseState !== 'pending') return
        //修改对象的状态
        that.PromiseState = 'resolved'
        //修改对象的值
        that.PromiseResult = data;
        //调用成功的回调函数
        
    };
    //reject函数
    function reject(data){
        //判断状态是否为pending
        if(that.PromiseState !== 'pending') return
        //修改对象的状态
        that.PromiseState = 'rejected'
        //修改对象的值
        that.PromiseResult = data;
    }
   executor(resolve,reject); 
}
//添加then()方法
Promise.prototype.then = function (onResolved,onRejected){

}
(4)throw抛出异常改变promise状态
(5)then方法执行回调
//添加then()方法 指定函数处理promise结果返回值
Promise.prototype.then = function (onResolved, onRejected) {
    if (this.PromiseState == 'fulfilled'){
        onResolved(this.PromiseResult)
    }
    if (this.PromiseState == 'rejected'){
        onRejected(this.PromiseResult)
    }
}
(6)异步任务回调的执行
//声明构造函数
function Promise(executor){//executor执行器参数
    //最开始的promise状态
    this.PromiseState = 'pending'
    //最开始的promise值
    this.PromiseResult = null;
    //保存实例对象的this值
    const that = this;
    //声明一个属性
    this.callback = {};
    //resolve函数
    function resolve(data){
        //判断状态是否为pending
        if(that.PromiseState !== 'pending') return
        //修改对象的状态
        that.PromiseState = 'resolved'
        //修改对象的值
        that.PromiseResult = data;
        //调用成功的回调函数
        if (that.callback.onResolved){
            that.callback.onResolved(data)
        }

    };
    //reject函数
    function reject(data){
        //判断状态是否为pending
        if(that.PromiseState !== 'pending') return
        //修改对象的状态
        that.PromiseState = 'rejected'
        //修改对象的值
        that.PromiseResult = data;
        //执行失败回调
        if(that.callback.onRejected){
            that.callback.onRejected(data)
        }
    }
    try{
        //同步调用 执行器函数
        executor(resolve,reject);
    }catch(err){
        //修改promise状态 为失败rejected
        reject(err)
    }
}

//添加then()方法 指定函数处理promise结果返回值
Promise.prototype.then = function (onResolved, onRejected) {
    if (this.PromiseState == 'fulfilled'){
        onResolved(this.PromiseResult)
    }
    if (this.PromiseState == 'rejected'){
        onRejected(this.PromiseResult)
    }
    if (this.PromiseState == 'pending'){//promise 状态为pending的时候执行
        // 保存回调函数
        this.callback = {
            onResolved:onResolved,
            onRejected:onRejected
        }
    }
}
(7)指定多个回调的实现
思路:先声明一个回调数组callbacks;在then的方法中保存回调函数 将{onResolved:onResolved,onRejected:onRejected}push到callbacks中;在resolve或者reject函数中,遍历调用成功/失败的回调函数
//声明构造函数
function Promise(executor){//executor执行器参数
    //最开始的promise状态
    this.PromiseState = 'pending'
    //最开始的promise值
    this.PromiseResult = null;
    //保存实例对象的this值
    const that = this;
    //声明一个属性
    this.callback = [];
    //resolve函数
    function resolve(data){
        //判断状态是否为pending
        if(that.PromiseState !== 'pending') return
        //修改对象的状态
        that.PromiseState = 'resolved'
        //修改对象的值
        that.PromiseResult = data;
        //遍历调用成功的回调函数
        that.callback.forEach(item=>{
            item.onResolved(data)
        })
       

    };
    //reject函数
    function reject(data){
        //判断状态是否为pending
        if(that.PromiseState !== 'pending') return
        //修改对象的状态
        that.PromiseState = 'rejected'
        //修改对象的值
        that.PromiseResult = data;
        //
        //遍历执行失败回调
        that.callback.forEach(item=>{
            item.onRejected(data)
        })
    }
    try{
        //同步调用 执行器函数
        executor(resolve,reject);
    }catch(err){
        //修改promise状态 为失败rejected
        reject(err)
    }
}

//添加then()方法 指定函数处理promise结果返回值
Promise.prototype.then = function (onResolved, onRejected) {
    if (this.PromiseState == 'fulfilled'){
        onResolved(this.PromiseResult)
    }
    if (this.PromiseState == 'rejected'){
        onRejected(this.PromiseResult)
    }
    if (this.PromiseState == 'pending'){//promise 状态为pending的时候执行
        // 保存回调函数
        this.callback.push({
            onResolved:onResolved,
            onRejected:onRejected
        });
    }
}
举报

相关推荐

0 条评论