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;
 
 
 
 
 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/zhx119/p/11522144.html
今日推荐