• [翻译]简单的实现一个Promise


            英文原文为:https://www.promisejs.org/implementing/

    1. 状态机

            因为 promise 对象是一个状态机,所以我们首先应该定义将要用到的状态。

    var PENDING = 0;
    var FULFILLED = 1;
    VAR REJECTED = 2;
    
    function Promise () {
        // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED
        var state = PENDING;
    
        // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息
        var value = null;
    
        // 存储被 .then 或 .done 方法调用的成功和失败的处理函数
        var handlers = [];
    }

    2. 转换

            接着,让我们来考虑一下两个可能发生的重要转换,fulfilling 和 rejecting:

    var PENDING = 0;
    var FULFILLED = 1;
    var REJECTED = 2;
    
    function Promise () {
        // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED
        var state = PENDING;
    
        // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息
        var value = null;
    
        // 存储被 .then 或 .done 方法调用的成功和失败的处理函数
        var handlers = [];
    
        function fulfill (result) {
            state = FULFILLED;
            value = result;
        }
    
        function reject (error) {
            state = REJECTED;
            value = error;
        }
    }

            这给了我们基础的低层转换,我们现在来考虑更高层的转换 resolve。

    var PENDING = 0;
    var FULFILLED = 1;
    var REJECTED = 2;
    
    function Promise () {
        // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED
        var state = PENDING;
    
        // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息
        var value = null;
    
        // 存储被 .then 或 .done 方法调用的成功和失败的处理函数
        var handlers = [];
    
        function fulfill (result) {
            state = FULFILLED;
            value = result;
        }
    
        function reject (error) {
            state = REJECTED;
            value = error;
        }
    
        function resolve (result) {
            try {
                var then = getThen(result);
                if (then) {
                    doResolve(then.bind(result), resolve, reject);
                    return;
                }
                fulfill(result);
            } catch (e) {
                reject(e);
            }
        }
    }

            注意 resolve 如何判断接收的是一个 promise 对象还是一个基本值(plain value),如果是一个 promise 对象,如何等待他完成。

    /** 
     * 检查值是否是一个 Promise 对象, 如果他是,
     * 返回这个 Promise 对象的‘then’方法。
     *
     * @param {Promise|Any} value
     * @return {Function|Null}
    */
    function getThen (value) {
        var t = typeof value;
        if (value && (t === 'object' || t === 'function')) {
            var then = value.then
            if (typeof then === 'function') {
                return then;
            }
        }
        return null;
    }
    
    /**
     * 潜在的解析函数,以确保 onFulfilled 和 onRejected 只执行其中的一个
     */
    function doResolve (fn, onFulfilled, onRejected) {
        var done = false;
        try {
            fn (function (value) {
                if (done) return
                done = true
                onFulfilled(value);
            }, function (reason) {
                if (done) return
                done = true
                onRejected(reason);
            })
        } catch (ex) {
            if (done) return
            done = true
            onRejected(ex);
        }
    }

    3. 构造

            我们现在有了完整的内部状态机,但我们还没有暴露出解决承诺(resolving promise)或观察它的方法。让我们从增加一个解决 promise 的方法开始。

    var PENDING = 0;
    var FULFILLED = 1;
    VAR REJECTED = 2;
    
    function Promise () {
        // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED
        var state = PENDING;
    
        // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息
        var value = null;
    
        // 存储被 .then 或 .done 方法调用的成功和失败的处理函数
        var handlers = [];
    
        function fulfill (result) {
            state = FULFILLED;
            value = result;
        }
    
        function reject (error) {
            state = REJECTED;
            value = error;
        }
    
        function resolve (result) {
            try {
                var then = getThen(result);
                if (then) {
                    doResolve(then.bind(result), resolve, reject);
                    return;
                }
                fulfill(result);
            } catch (e) {
                reject(e);
            }
        }
    
        doResolve(fn, resolve, reject);
    }

            你可以看到,我们复用了 doResolve,因为我们有另一个不可信的解析。fn 允许多次调用 resolve 和 reject,甚至抛出异常。我们要确保 promise 只 resolve 一次或 reject 一次,然后再也不会过渡到另一个状态。

    4. 观察(使用 .done)

            我们现在拥有一个已完成的状态机,但是我们仍没有办法去观察它的变化。我们的最终目的是实现 .then,但是 .done 的语义要简单的多,所以我们首先实现它。

            我们这里的目标是实现 promise.done(onFulfilled, onRejected):

    • 只调用 onFulfilled 或 onRejected 中的一个
    • 它是调用一次
    • 它在下一时刻被调用(例如,在 .done 方法已经返回后)
    • 不管我们在调用之前或之后是否解决了这个问题,它都被调用了。
    var PENDING = 0;
    var FULFILLED = 1;
    var REJECTED = 2;
    
    function Promise (fn) {
        // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED
        var state = PENDING;
    
        // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息
        var value = null;
    
        // 存储被 .then 或 .done 方法调用的成功和失败的处理函数
        var handlers = [];
    
        function fulfill(result) {
            state = FULFILLED;
            value = result;
            handlers.forEach(handle);
            handlers = null;
        }
    
        function reject (result) {
            state = REJECTED
            value = result
            handlers.forEach(handle)
            handlers = null
        }
    
        function resolve (result) {
            try {
                var then = getThen(result)
                if (then) {
                    doResolve(then, resolve, reject)
                    return
                }
                fulfill(result)
            } catch (ex) {
                reject(ex)
            }
        }
    
        function handle (handler) {
            if (state === PENDING) {
                handlers.push(handler);
            } else {
                if (state === FULFILLED && typeof handlers.onFulfilled === 'function') {
                    handler.onFulfilled(value);
                }
                if (state === REJECTED && typeof handlers.onRejected === 'function') {
                    handler.onRejected(value);
                }
            }
        }
    
        this.done = function (onFulfilled, onRejected) {
            // 确保我们总是异步执行的
            setTimeout(function () {
                handler({
                    onFulfilled: onFulfilled,
                    onRejected: onRejected
                })
            }, 0)
        }
        
        doResolve(fn, resolve, reject);
    }

            当 Promise 被解决或拒绝时,我们要确保去通知 handlers。

    5. 观察(使用 .then)

            现在我们已经实现了 .done,我们可以简单的实现 .then 来实现相同的事情,但是在程序中构造一个新的 Promise 对象。

    this.then = function (onFulfilled, onRejected) {
        var self = this;
        return new Promise(function (resolve, reject) {
            return self.done(function (result) {
                if (typeof onFulfilled === 'function') {
                    try {
                        return resolve(onFulfilled(result));
                    } catch (ex) {
                        return reject(ex);
                    }
                } else {
                    return resolve(result);
                }
            }, function (error) {
                if (typeof onRejected === 'function') {
                    try {
                        return resolve(onRejected(error));
                    } catch (ex) {
                        return reject(ex);
                    }
                } else {
                    return reject(error);
                }
            });
        });
    }
  • 相关阅读:
    使用MongoDB ruby驱动进行简单连接/CRUD/运行命令
    DBMS-SQL:聚集函数、嵌套子查询、数据库修改
    国内无法使用gem install解决办法
    AI-Local search&Nodeterministic Problems&Partial observations&Online search
    DBMS-关系模型
    DBMS-基本概念
    ros安装过程中部分包“hash校验和不符”报错解决办法
    AI: Chapter 3-Solving problems by searching
    Map数据结构
    Set和WeakSet数据结构
  • 原文地址:https://www.cnblogs.com/SyMind/p/8530429.html
Copyright © 2020-2023  润新知