zoukankan      html  css  js  c++  java
  • kriskowal/q 学习笔记

    q/promise

    promise 实现

    
    // demo
     Q.Promise(function(resolve, reject, notify) {}
      .then()
    
    
    
    执行流程
    
    Promise - > then - > NextTick(放入task队列) -- > flush(下一个循环, 执行队列) --> 执行 defer.promiseDispatch (resolve等放入message) -- > 执行 defer.become -- > NextTick(放入task队列)
    -- > flush(下一个循环, 执行队列) -- > 执行 promise.promiseDispatch(执行resolve等方法) -- > 完成
    
    // 解析
    function promise(resolver) {
        if (typeof resolver !== "function") {
            throw new TypeError("resolver must be a function.");
        }
        var deferred = defer(); // 延迟执行对象
        try {
            resolver(deferred.resolve, deferred.reject, deferred.notify); // (resolve,reject) = > {}
        } catch (reason) {
            deferred.reject(reason);
        }
        return deferred.promise;
    }
    
    function defer() {
        // if "messages" is an "Array", that indicates that the promise has not yet
        // been resolved.  If it is "undefined", it has been resolved.  Each
        // element of the messages array is itself an array of complete arguments to
        // forward to the resolved promise.  We coerce the resolution value to a
        // promise using the `resolve` function because it handles both fully
        // non-thenable values and other thenables gracefully.
        var messages = [], progressListeners = [], resolvedPromise;
    
        var deferred = object_create(defer.prototype); // 创建 defer
        var promise = object_create(Promise.prototype); // 创建 promise,作为 defer 的 promise 返回
    
        promise.promiseDispatch = function (resolve, op, operands) {
            var args = array_slice(arguments);
            if (messages) {
                messages.push(args); // 添加 args
                if (op === "when" && operands[1]) { // progress operand
                    progressListeners.push(operands[1]);
                }
            } else {
                Q.nextTick(function () {
                    resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
                });
            }
        };
    
        // XXX deprecated
        promise.valueOf = function () {
            if (messages) {
                return promise;
            }
            var nearerValue = nearer(resolvedPromise);
            if (isPromise(nearerValue)) {
                resolvedPromise = nearerValue; // shorten chain
            }
            return nearerValue;
        };
    
        promise.inspect = function () {
            if (!resolvedPromise) {
                return { state: "pending" };
            }
            return resolvedPromise.inspect();
        };
    
        if (Q.longStackSupport && hasStacks) {
            try {
                throw new Error();
            } catch (e) {
                // NOTE: don't try to use `Error.captureStackTrace` or transfer the
                // accessor around; that causes memory leaks as per GH-111. Just
                // reify the stack trace as a string ASAP.
                //
                // At the same time, cut off the first line; it's always just
                // "[object Promise]
    ", as per the `toString`.
                promise.stack = e.stack.substring(e.stack.indexOf("
    ") + 1);
                promise.stackCounter = longStackCounter++;
            }
        }
    
        // NOTE: we do the checks for `resolvedPromise` in each method, instead of
        // consolidating them into `become`, since otherwise we'd create new
        // promises with the lines `become(whatever(value))`. See e.g. GH-252.
    
        function become(newPromise) {
            resolvedPromise = newPromise;
    
            if (Q.longStackSupport && hasStacks) {
                // Only hold a reference to the new promise if long stacks
                // are enabled to reduce memory usage
                promise.source = newPromise;
            }
    
            array_reduce(messages, function (undefined, message) {
                Q.nextTick(function () {
                    newPromise.promiseDispatch.apply(newPromise, message); // 执行 resolve
                });
            }, void 0);
    
            messages = void 0;
            progressListeners = void 0;
        }
    
        deferred.promise = promise;
        deferred.resolve = function (value) {
            if (resolvedPromise) {
                return;
            }
    
            become(Q(value));
        };
    
        deferred.fulfill = function (value) {
            if (resolvedPromise) {
                return;
            }
    
            become(fulfill(value));
        };
        deferred.reject = function (reason) {
            if (resolvedPromise) {
                return;
            }
    
            become(reject(reason));
        };
        deferred.notify = function (progress) {
            if (resolvedPromise) {
                return;
            }
    
            array_reduce(progressListeners, function (undefined, progressListener) {
                Q.nextTick(function () {
                    progressListener(progress);
                });
            }, void 0);
        };
    
        return deferred;
    }
    
    
    Q.makePromise = Promise;
    function Promise(descriptor, fallback, inspect) {
        if (fallback === void 0) {
            fallback = function (op) {
                return reject(new Error(
                    "Promise does not support operation: " + op
                ));
            };
        }
        if (inspect === void 0) {
            inspect = function () {
                return {state: "unknown"};
            };
        }
    
        var promise = object_create(Promise.prototype);
    
        promise.promiseDispatch = function (resolve, op, args) {
            var result;
            try {
                if (descriptor[op]) {
                    result = descriptor[op].apply(promise, args);
                } else {
                    result = fallback.call(promise, op, args);
                }
            } catch (exception) {
                result = reject(exception);
            }
            if (resolve) {
                resolve(result);
            }
        };
    
        promise.inspect = inspect;
    
        // XXX deprecated `valueOf` and `exception` support
        if (inspect) {
            var inspected = inspect();
            if (inspected.state === "rejected") {
                promise.exception = inspected.reason;
            }
    
            promise.valueOf = function () {
                var inspected = inspect();
                if (inspected.state === "pending" ||
                    inspected.state === "rejected") {
                    return promise;
                }
                return inspected.value;
            };
        }
    
        return promise;
    }
    
    // then 方法
    Promise.prototype.then = function (fulfilled, rejected, progressed) {
        var self = this;
        var deferred = defer();
        var done = false;   // ensure the untrusted promise makes at most a
                            // single call to one of the callbacks
    
        function _fulfilled(value) {
            try {
                return typeof fulfilled === "function" ? fulfilled(value) : value;
            } catch (exception) {
                return reject(exception);
            }
        }
    
        function _rejected(exception) {
            if (typeof rejected === "function") {
                makeStackTraceLong(exception, self);
                try {
                    return rejected(exception);
                } catch (newException) {
                    return reject(newException);
                }
            }
            return reject(exception);
        }
    
        function _progressed(value) {
            return typeof progressed === "function" ? progressed(value) : value;
        }
    
        // 在下一次 执行
        Q.nextTick(function () {
            self.promiseDispatch(function (value) {
                if (done) {
                    return;
                }
                done = true;
    
                deferred.resolve(_fulfilled(value));
            }, "when", [function (exception) {
                if (done) {
                    return;
                }
                done = true;
    
                deferred.resolve(_rejected(exception));
            }]);
        });
    
        // Progress propagator need to be attached in the current tick.
        self.promiseDispatch(void 0, "when", [void 0, function (value) {
            var newValue;
            var threw = false;
            try {
                newValue = _progressed(value);
            } catch (e) {
                threw = true;
                if (Q.onerror) {
                    Q.onerror(e);
                } else {
                    throw e;
                }
            }
    
            if (!threw) {
                deferred.notify(newValue);
            }
        }]);
    
        return deferred.promise;
    };
    
    
    //catch 方法
    Promise.prototype["catch"] = function (rejected) {
        return this.then(void 0, rejected);
    };
    
    
  • 相关阅读:
    Docker--使用
    腾讯云发送短信
    Mysql--查询基础
    flask10--数据库链接池(通用),wtforms
    Flask11--Flask-script,sqlalchemy
    序列化 json
    第五章-算术运算符
    计算机网络自顶向下的方法-第二章 应用层
    第三章-数据类型
    第三章-常量和宏定义
  • 原文地址:https://www.cnblogs.com/SLchuck/p/13822016.html
Copyright © 2011-2022 走看看