详细拆解Promise的使用到自定义封装

一、promise介绍和基本使用

一.基本介绍
概念上:promise是一门新的技术,E6中新出的规范,是用来解决JS中进行异步编程的新的解决方案(旧的方案是单纯的使用回调函数,会造成回调地狱)
表达上:是回调函数的形式,主要通过promise对象用来封装一个异步操作并可以获取其成功失败的结果值
优势:
1.指定回调函数的方式更加灵活

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

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

旧的:回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套函数的回调执行的条件
promise:链式回调

扩展:异步编程
1.fs 文件操作 (node.js下的一个模块,可以对计算机中的磁盘进行读写操作)
require(“fs”).readfile(“./index.html”),(err,data)=>{} //异步函数回调
2.数据库操作
3.AJAX网络请求
4.定时器

二、基本使用
2.1promise基本使用

 <div class="div">点击抽奖</div>
    <script>
        //    随机函数
        var random = function (m, n) {
    
    
            return Math.ceil(Math.random() * (n - m + 1) + m - 1)
        }
        // 获取页面的元素
        let btn = document.querySelector(".div")
        // 绑定单机事件
        btn.addEventListener("click", function () {
    
      //点击事件click
            // console.log("hhh");
            // 1秒后执行回调


            // 1.普通的回调函数
            setTimeout(() => {
    
    
                // 从1开始生成随机数取值区间为1000
                let n = random(1,100)
                if(n<=30){
    
    
                    alert("中奖啦")
                }else {
    
    
                    alert("再接再厉")
                }
            }, 1000);


            // 2.promise 
            // reslove 异步任务成功解决 都是函数类型的数据
            // reject 异步任务失败拒绝 都是函数类型的数据
            let p = new Promise((reslove, reject) => {
    
     //实例化一个promise对象时里面接收的一个函数类型的参数
                // 里面包裹一个异步函数
                setTimeout(() => {
    
    
                    // 从1开始生成随机数取值区间为1000
                    let n = random(1, 100)
                    if (n <= 30) {
    
    
                        // 将n当成结果值传递给两个函数后面的then方法就会接收到结果值
                        // 成功的时候调用
                        reslove(n) //调用后可以将promise对象(p)的状态设置为成功

                    } else {
    
    
                        reject(n) //调用后可以将promise对象(p)的状态设置为失败

                    }
                }, 1000);
            })

            // 调用then方法(两个回调函数) 第一个成功的回调
            p.then((value) => {
    
    
                alert("中奖啦,中奖数字为"+value)
            }, (reason) => {
    
     //第二个失败的回调
                alert("再接再厉"+ reason)
            })

        })
    </script>

2.2promise封装fs读取文件的操作

//1.基本操作
 //  node.js中
        // 1.引入fs
        const fs = require('fs')
        // fs中有一个方法是readFil读取文件,一个是读取文件的路径,第二个是成功和失败的回调
        fs.readFile('./resource/content', (err, data) => {
    
    
            //    如果出错抛出错误
            if (err) throw err
            // 没有出错输出文件
            console.log(data);
        })

        //    promise封装
        const p = new Promise((resolve, reject) => {
    
    
            fs.readFile('./resource/content', (err, data) => {
    
    
                //    如果出错抛出错误  记住得把结果值传入进去
                if (err) reject(err)
                // 没有出错输出文件
                resolve(data)
            })
        })
        p.then(value=> {
    
    
            console.log(value.toString());
        },reason => {
    
    
            throw reason
            })
//2.封装一个函数
 //    封装一个读取fs文件的函数(promise处理异步)
        // 参数:路径:path
        // 返回值promise对象
        function mineReadFile(path) {
    
    
            return new Promise((resolve, reject) => {
    
    
                require("fs").readFile(path, (err, data) => {
    
    
                    if(err) reject(err)
                    resolve(data)
                })
            })
        
       // 因为上面额函数返回值就是promise,因此可以直接在函数的返回值进行使用then方法
        mineReadFile('./resource/content').then((value)=>{
    
    
            console.log(value);
        },(reason)=>{
    
    
            console.log(reason);
        })

//3.node.js内部函数 util.promisify(original):传入一个遵循常见的错误优先的回调函数,并返回一个promise的版本
 let util = require("util")
        let fs = require('fs')
        // 返回一个新的函数返回的结果就是promise对象
        let mineReadFile = util.promisify(fs.readFile)
        // 因为上面额函数返回值就是promise,因此可以直接在函数的返回值进行使用then方法
        mineReadFile('./resource/content').then((value)=>{
    
    
            console.log(value);
        },(reason)=>{
    
    
            console.log(reason);
        })

2.3promise封装ajax

//1.基本使用
 <div class="btn">点击发送请求</div>
    <script>
        //接口地址:http://api.a
        let btn = document.querySelector(".btn")

        btn.addEventListener("click", function () {
    
    
            let p = new Promise((resolve, reject) => {
    
    
                // 发送ajax请求
                // 1.创建对象
                const xhr = new XMLHttpRequest()
                // 2.初始化请求方式和请求地址
                xhr.open("GET", 'http://api.a')
                // 3.发送
                xhr.send()
                // 4.处理响应
                xhr.onreadystatechange = function () {
    
    
                    if (xhr.readyState == 4) {
    
    
                        // 判断响应状态码
                        if (xhr.status >= 200 && xhr.status < 300) {
    
    
                            resolve(xhr.response)
                        } else {
    
    
                            reject(xhr.status)
                        }
                    }
                }
            })
            p.then((value) => {
    
    
                console.log(value);
            }, (reason) => {
    
    
                console.log(reason);
            })
        })
//2.封装一个函数
  function senAjax(url) {
    
    
            return new Promise((resolve, reject) => {
    
    
                let xhr = new XMLHttpRequest()
                xhr.responseText = 'json' //ajax将响应文本转换为json格式
                xhr.open('GET', url)
                xhr.send()
                xhr.onreadystatechange = function () {
    
    
                    if (xhr.readyState == 4) {
    
     //为4是所有结果都返回时的一个状态
                        if (xhr.status >= 200 && xhr.status < 300) {
    
    
                            resolve(xhr.response)
                        } else {
    
    
                            reject(xhr.status)
                        }
                    }
                }
            })
        }
        senAjax('http:/nn').then((value) => {
    
    
            console.log(value);
        }, (reason) => {
    
    
            console.log(reason);

    </script>

二、promise的API

在这里插入图片描述
1、promiseState:promise对象中状态属性

  • pending 未决定的
  • resloved / fullfilled 成功
  • rejected 失败
    改变状态只有这两种(而且这个状态只能改变一次)
  • pending -> resloved (数据结果一般为value)
  • pending->rejected (数据结果一般为reason)

2、promiseResult:promise对象的值
概念:保存的是异步任务保存失败或者成功的结果

  • resloved
  • rejected 这两个函数进行更改,然后通过then方法就可以对值进行操作

3、promise构造函数:promise(excutor){}

  • excutor函数:执行器(resolve,reject)=>{} 立即执行是同步的
  • resolve 内部定义成功时调用的函数 value=>{}
  • reject 内部定义失败时调用的函数 reason =>{}

4、Promise.prototype.then 方法:(onResoved,onRejected)=>{}

  • 指定用于得到value成功的回调。失败的reason的失败回调,返回一个新的promise对象

5、Promise.prototype.catch方法:(onRejected)=>{}

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

6.Promise.resolve 方法: (value) => {}

  • value: 成功的数据或 promise 对象
  • 说明 : 返回一个成功/失败的 promise 对象
let p = Promise.resolve(123)
        console.log(p); //返回一个成功或者失败的promise对象 失败只由传入是promise的失败决定

7.Promise.reject 方法: (reason) => {}

  • reason: 失败的原因
  • 说明 : 返回一个失败的 promise 对象
 let p = Promise.reject(123)
        let p1 = Promise.reject(new Promise((resolve,reject)=>{
    
    
            resolve("成功")
        }))
        console.log(p1); //返回一个失败的promise对象 正常数值也是失败,传入的是promise对象也是失败,但是会存储传入promise的数值状态

8.Promise.all 方法: (promises) => {}

  • promises: 包含 n 个 promise 的数组
  • 说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就
    直接失败

9.Promise.race 方法: (promises) => {}

  • promises: 包含 n 个 promise 的数组
  • 说明 : 返回一个新的 promise, 第一个完成的 p

三、promise的关键问题

  1. 如何改变 promise 的状态?

(1) resolve(value): 如果当前是 pendding 就会变为 resolved
(2) reject(reason): 如果当前是 pendding 就会变为 rejected
(3) 抛出异常: 如果当前是 pendding 就会变为 rejected

  1. 一个 promise 指定多个成功/失败回调函数, 都会调用吗?

当 promise 改变为对应状态时都会调用,并且不会覆盖

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

  2. promise.then()返回的新 promise 的结果状态由什么决定?

(1) 简单表达: 由 then()指定的回调函数执行的结果决定,也就是then指定的回调函数返回结果决定(undefind等只要不是新的promise的失败回调都是成功)
(2) 详细表达:
1 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
2 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
3 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果

  1. promise 如何串连多个操作任务?

(1) promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
(2) 通过 then 的链式调用串连多个同步/异步任务

  1. promise 异常传透?

(1) 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调, (2) 前面任何操作出了异常, 都会传到最后失败的回调中处理

  1. 中断 promise 链?

(1) 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
(2) 办法: 在回调函数中返回一个 pendding 状态的 promise 对象

四、promise自定义封装

1.构造函数封装

//声明构造函数
function Promise(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 方法
Promise.prototype.then = function(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 方法
Promise.prototype.catch = function(onRejected){
    
    
    return this.then(undefined, onRejected);
}

//添加 resolve 方法
Promise.resolve = function(value){
    
    
    //返回promise对象
    return new Promise((resolve, reject) => {
    
    
        if(value instanceof Promise){
    
    
            value.then(v=>{
    
    
                resolve(v);
            }, r=>{
    
    
                reject(r);
            })
        }else{
    
    
            //状态设置为成功
            resolve(value);
        }
    });
}

//添加 reject 方法
Promise.reject = function(reason){
    
    
    return new Promise((resolve, reject)=>{
    
    
        reject(reason);
    });
}

//添加 all 方法
Promise.all = function(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 方法
Promise.race = function(promises){
    
    
    return new Promise((resolve, reject) => {
    
    
        for(let i=0;i<promises.length;i++){
    
    
            promises[i].then(v => {
    
    
                //修改返回对象的状态为 『成功』
                resolve(v);
            },r=>{
    
    
                //修改返回对象的状态为 『失败』
                reject(r);
            })
        }
    });
}

2.类的封装

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

async函数:
1.函数的返回值为promise对象
2.promise对象的结果由async函数执行的返回值决定

await表达式
1.await右侧的表达式一般为promise对象,但也可以是其它的值,如果表达式是其它值,直接将此值作为await的返回值
2.如果表达式是promise对象,await返回的是promise成功的值

注意:
1.await必须写在async函数中,但async函数中可以没有await
2.如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理

猜你喜欢

转载自blog.csdn.net/qq_59079803/article/details/125074582