JavaScript异步与Promise实现

2020-03-10  本文已影响0人  凡凡的小web

原文https://zhuanlan.zhihu.com/p/26815654

Promise实现
Promise是什么,怎么样使用就介绍到此,另外一个问题是面试过程中经常也会被提及的:如何实现一个Promise,当然,限于篇幅,我们这里只讲思路,不会长篇大论。

构造函数
首先创建一个构造函数,供实例化创建promise,该构造函数接受一个函数参数,实例化时,会立即调用该函数,然后返回一个Promise对象:

var MyPromise = (() => {
var value = undefined; // 当前Promise
var tasks = []; // 完成回调队列
var rejectTasks = []; // 拒绝回调队列
var state = 'pending'; // Promise初始为等待态

    // 辅助函数,使异步回调下一轮事件循环执行
    var nextTick = (callback) => {
        setTimeout(callback, 0);
    };

    // 辅助函数,传递Promsie的状态值
    var ref = (value) => {
        if (value && typeof value.then === 'function') {
            // 若状态值为thenable对象或Promise,直接返回
            return value;
        }
        // 否则,将最终值传递给下一个then方法注册的回调函数
        return {
            then: function(callback) {
                return ref(callback(value));
            }
        }
    };
    var resolve = (val) => {};
    var reject = (reason) => {};

    function MyPromise(func) {
        func(resolve.bind(this), reject.bind(this));
    }

    return MyPromise;
});

静态方法
在实例化创建Promise时,我们会将构造函数的两个静态方法:resolve和reject传入初始函数,接下来需要实现这两个函数:

var resolve = (val) => {
if (tasks) {
value = ref(val);
state = 'resolved'; // 将状态标记为已完成
// 依次执行任务回调
tasks.forEach((task) => {
value = nextTick((val) => {task0;});
});
tasks = undefined; // 决议后状态不可变

        return this;
    }
};
var reject = (reason) => {
    if (tasks) {
        value = ref(reason);
        state = 'rejected'; // 将状态标记为已完成

        // 依次执行任务回调
        tasks.forEach((task) => {
            nextTick((reason) => {task[1](value);});
        });
        tasks = undefined; // 决议后状态不可变

        return this;
    }
};

还有另外两个静态方法,原理还是一样,就不细说了。

实例方法
目前构造函数,和静态方法完成和拒绝Promise都已经实现,接下来需要考虑的是Promise的实例方法和链式调用:

MyPromise.prototype.then = (onFulfilled, onRejected) => {
    onFulfilled = onFulfilled || function(value) {
        // 默认的完成回调
        return value;
    };
    onRejected = onRejected || function(reason) {
        // 默认的拒绝回调
        return reject(reason);
    };

    if (tasks) {
        // 未决议时加入队列
         tasks.push(onFulfilled);
         rejectTasks.push(onRejected);
    } else {
        // 已决议,直接加入事件循环执行
         nextTick(() => {
             if (state === 'resolved') {
                 value.then(onFulfilled);
             } else if (state === 'rejected') {
                 value.then(onRejected);
             }
         });
    }

    return this;
};

实例
以上可以简单实现Promise部分异步管理功能:

var promise = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('完成');
    }, 0);
});
promise.then((msg) => {console.log(msg);});

本篇由回调函数起,介绍了回调处理异步任务的常见问题,然后介绍Promises/A+规范及Promise使用,最后就Promise实现做了简单阐述(之后有机会会详细实现一个Promise),花费一周终于把基本知识点介绍完,下一篇将介绍JavaScript异步与生成器实现。

上一篇 下一篇

猜你喜欢

热点阅读