zoukankan      html  css  js  c++  java
  • Promise详解与实现(Promise/A+规范)

    1.什么是Promise?

    Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一

    2.对于几种常见异步编程方案

    • 回调函数
    • 事件监听
    • 发布/订阅
    • Promise对象

    这里就拿回调函数说说

    1.对于回调函数 我们用Jquery的ajax获取数据时 都是以回调函数方式获取的数据

    $.get(url, (data) => {
        console.log(data)
    )
    2.如果说 当我们需要发送多个异步请求 并且每个请求之间需要相互依赖 那这时 我们只能 以嵌套方式来解决 形成 "回调地狱"
    $.get(url, data1 => {
        console.log(data1)
        $.get(data1.url, data2 => {
            console.log(data1)
        })
    })
    这样一来,在处理越多的异步逻辑时,就需要越深的回调嵌套,这种编码模式的问题主要有以下几个:
    • 代码逻辑书写顺序与执行顺序不一致,不利于阅读与维护。
    • 异步操作的顺序变更时,需要大规模的代码重构。
    • 回调函数基本都是匿名函数,bug 追踪困难。
    • 回调函数是被第三方库代码(如上例中的 ajax )而非自己的业务代码所调用的,造成了 IoC 控制反转。

    Promise 处理多个相互关联的异步请求

    1.而我们Promise 可以更直观的方式 来解决 "回调地狱"

    const request = url => { 
        return new Promise((resolve, reject) => {
            $.get(url, data => {
                resolve(data)
            });
        })
    };
    
    // 请求data1
    request(url).then(data1 => {
        return request(data1.url);   
    }).then(data2 => {
        return request(data2.url);
    }).then(data3 => {
        console.log(data3);
    }).catch(err => throw new Error(err));
    2.相信大家在 vue/react 都是用axios fetch 请求数据 也都支持 Promise API
    import axios from 'axios';
    axios.get(url).then(data => {
       console.log(data)
    })
    Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中

    3.Promise使用

    1.Promise 是一个构造函数, new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数, excutor有两个函数类型形参resolve reject

    const promise = new Promise((resolve, reject) => {
           // 异步处理
           // 处理结束后、调用resolve 或 reject
    });

    2.promise相当于一个状态机

    promise的三种状态

    • pending
    • fulfilled
    • rejected

    1.promise 对象初始化状态为 pending
    2.当调用resolve(成功),会由pending => fulfilled
    3.当调用reject(失败),会由pending => rejected

    注意promsie状态 只能由 pending => fulfilled/rejected, 一旦修改就不能再变

    3.promise对象方法

    1.then方法注册 当resolve(成功)/reject(失败)的回调函数

    // onFulfilled 是用来接收promise成功的值
    // onRejected 是用来接收promise失败的原因
    promise.then(onFulfilled, onRejected);
    then方法是异步执行的
    2.resolve(成功) onFulfilled会被调用
    const promise = new Promise((resolve, reject) => {
       resolve('fulfilled'); // 状态由 pending => fulfilled
    });
    promise.then(result => { // onFulfilled
        console.log(result); // 'fulfilled' 
    }, reason => { // onRejected 不会被调用
        
    })
    3.reject(失败) onRejected会被调用
    const promise = new Promise((resolve, reject) => {
       reject('rejected'); // 状态由 pending => rejected
    });
    promise.then(result => { // onFulfilled 不会被调用
      
    }, reason => { // onRejected 
        console.log(rejected); // 'rejected'
    })
    4.promise.catch
    在链式写法中可以捕获前面then中发送的异常
    promise.catch(onRejected)
    相当于
    promise.then(null, onRrejected);
    
    // 注意
    // onRejected 不能捕获当前onFulfilled中的异常
    promise.then(onFulfilled, onRrejected); 
    
    // 可以写成:
    promise.then(onFulfilled)
           .catch(onRrejected); 

    4.promise chain

    promise.then方法每次调用 都返回一个新的promise对象 所以可以链式写法

    function taskA() {
        console.log("Task A");
    }
    function taskB() {
        console.log("Task B");
    }
    function onRejected(error) {
        console.log("Catch Error: A or B", error);
    }
    
    var promise = Promise.resolve();
    promise
        .then(taskA)
        .then(taskB)
        .catch(onRejected) // 捕获前面then方法中的异常

    5.Promise的静态方法

    1.Promise.resolve 返回一个fulfilled状态的promise对象

    Promise.resolve('hello').then(function(value){
        console.log(value);
    });
    
    Promise.resolve('hello');
    // 相当于
    const promise = new Promise(resolve => {
       resolve('hello');
    });
    2.Promise.reject 返回一个rejected状态的promise对象
    Promise.reject(24);
    new Promise((resolve, reject) => {
       reject(24);
    });
    3.Promise.all 接收一个promise对象数组为参数
    const p1 = new Promise((resolve, reject) => {
        resolve(1);
    });
    
    const p2 = new Promise((resolve, reject) => {
        resolve(2);
    });
    
    const p3 = new Promise((resolve, reject) => {
        reject(3);
    });
    
    Promise.all([p1, p2, p3]).then(data => { 
        console.log(data); // [1, 2, 3] 结果顺序和promise实例数组顺序是一致的
    }, err => {
        console.log(err);
    });
     

    4. Promise 代码自己实现

    // 自己实现Promise类

    function Promise(executor) {
        // 定义一个状态 表示当前promise状态
        let _this = this;
        _this.status = "pending"; // 默认promise状态是等待态
        _this.value = undefined;
        _this.reason = undefined;
        // 存放所有成功的回调
        _this.onResolvedCallbacks = [];
        // 存放所有失败的回调
        _this.onRejectedCallbacks = [];
        function resolve(value) {
            // 只能从等待态变成功态
            if (_this.status === "pending") {
                _this.status = "fulfilled";// 状态变为成功态
                _this.value = value;
                _this.onResolvedCallbacks.forEach(fn => fn());
            }
        }

        function reject(reason) {
            //  // 只能从等待态变失败态
            if (_this.status === "pending") {
                _this.status = "rejected"; //  状态变为失败态
                _this.reason = reason;
                _this.onRejectedCallbacks.forEach(fn => fn());
            }
        }
        //可能执行excecute时候报错
        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }
    // 这个函数的作用主要就是判断x 是不是普通的值还是promsie
    // 然后返回对应的成功状态或者失败状态进行传递值
    function resolvePromise(promise2, x, resolve, reject) {
        //判断promise 是否等于自身
        if (x === promise2) {
            return reject(new TypeError("循环引用"));
        }

        if (x != null && typeof x === 'object' || typeof x === "function") {
            // 可能是promise
            try { //定义变量把then取出来
                let then = x.then; // then属性有可能会抛异常
                if (typeof then === "function") {
                    // 认为是一个promise
                    //then.call确保then指向返回的promise 然后是成功或者失败
                    then.call(x, (y) => {
                        resolve(y)
                    }, (r) => {
                        reject(r);
                    });
                } else {
                    //x 是一个普通的d对象值
                    resolve(x);
                }
            } catch (e) {
                reject(e);
            }

        } else {
            // 不是引用类型 普通值 12 "avc"
            resolve(x);
        }
    }
    // 定义then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : data => data;
        onRejected = typeof onRejected === 'function' ? onRejected : reson => { throw reson };//reson => { throw reson }
        let _this = this;
        // then被执行 需要再次返回一个新的promise实例
        // 需要拿到当前then方法 成功或者失败的结果
        let promise2 = new Promise(function (resolve, reject) {
            if (_this.status === "fulfilled") {
                setTimeout(() => {
                    // 需要使用到promise2 放入异步中
                    try {
                        let x = onFulfilled(_this.value);
                        //resolve(x);
                        // 对x进行判断
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }
            if (_this.status === "rejected") {
                setTimeout(() => {
                    try {
                        let x = onRejected(_this.reason);
                        // 对x进行判断
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            }
            if (_this.status === "pending") {
                _this.onResolvedCallbacks.push(function () {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(_this.value);
                            // 对x进行判断
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
                _this.onRejectedCallbacks.push(function () {
                    setTimeout(() => {
                        try {
                            let x = onRejected(_this.reason);
                            // 对x进行判断
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
            }
        });
        return promise2;
    }

    // 导出该构造函数
    module.exports = Promise;
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    下载安装安卓开发工具
    斐波那契数列
    各位相加
    求连续最大子序列和
    反转字符串中的单词
    统计位数为偶数的数字
    Express框架的整体感知
    node.js当中的http模块与url模块的简单介绍
    formidable处理提交的表单或文件的简单介绍
    30分钟,学会经典小游戏编程!
  • 原文地址:https://www.cnblogs.com/zhx119/p/11522144.html
Copyright © 2011-2022 走看看