zoukankan      html  css  js  c++  java
  • Nodejs的Promise库

    今天研究了下nodejs的Promise库,发现学到了不少,他的源代码不多,但是很精辟,我加了点注释,可能比不加还难懂。。。凑活着看吧。。

    库:https://npmjs.org/package/promise

    Promise/A+规范:http://promises-aplus.github.io/promises-spec/


    core.js

    'use strict'
    
    var nextTick = require('./lib/next-tick')
    
    module.exports = Promise
    function Promise(fn) {
    
        // 如果不是一个Promise对象,那么调用构造函数包装下
        if (!(this instanceof Promise)) return new Promise(fn)
    
        // 参数必须是一个函数
        if (typeof fn !== 'function') throw new TypeError('not a function')
    
        var state = null
        var delegating = false
        var value = null
        var deferreds = []
        var self = this
    
        // 成员函数:then。返回Promise2
        this.then = function (onFulfilled, onRejected) {
            // 返回一个新的Promise,Promise2。
            return new Promise(function (resolve, reject) {
                // Handler没特别的,就是为了保存4个参数
                handle(new Handler(onFulfilled, onRejected, resolve, reject))
            })
        }
    
        // 处理defer,fulfill, reject等问题
        //
        function handle(deferred) {
            // 还在pending?那么走人
            if (state === null) {
                deferreds.push(deferred)
                return
            }
            // 状态已变:
            nextTick(function () {
                // 根据state来决定是调用fulfill还是reject
                var cb = state ? deferred.onFulfilled : deferred.onRejected
                if (cb === null) {
                    // 假如没有提供对应的callback,那么调用“默认”的回调
                    (state ? deferred.resolve : deferred.reject)(value)
                    return
                }
    
                // 调用对应的回调
                var ret
                try {
                    ret = cb(value)
                }
                catch (e) {
                    // 出现异常了,那么把状态改成reject
                    deferred.reject(e)
                    return
                }
    
                // 回调运行没问题,那么就把回调的返回值作为自己的值,状态变成fulfilled
                deferred.resolve(ret)
            })
        }
    
        // 作为第一个参数传给你写的那个函数
        //
        function resolve(newValue) {
            // 这里有点没搞懂,为啥要针对delegating flag来return,
            // 其实假如delegating标记已设置,这个函数就再也进不来了呀。
            // 难道仅仅为了防止出错?
            if (delegating)
                return
            resolve_(newValue)
        }
    
        function resolve_(newValue) {
            // 说明已经被处理过了!不用再处理了,其实如果会被调用两次,应该是出错了!
            if (state !== null)
                return
            try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
                if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
    
                // resolve的返回值可以是普通值,也可以是一个promise,针对promise要特殊处理下
                if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
    
                    // 判别他是不是一个promise
                    var then = newValue.then
                    if (typeof then === 'function') {
    
                        // 是的。。那就有点麻烦,设个标记先
                        delegating = true
                        // 根据 Promise/A+,当前promise的状态保持pending,且依赖于返回的promise的状态,即newValue
                        // 所以调用 newValue.then。
                        then.call(newValue, resolve_, reject_)
                        return
                    }
                }
    
                // 普通值,简单了
                state = true
                value = newValue
                // 触发依赖于这个promise的所有回调(通过then设置上去的)
                finale()
            } catch (e) { reject_(e) }
        }
    
        // 作为第二个参数传给你写的那个函数
        //
        function reject(newValue) {
            if (delegating)
                return
            reject_(newValue)
        }
    
        function reject_(newValue) {
            if (state !== null)
                return
            state = false
            value = newValue
            finale()
        }
    
        // 触发依赖于这个promise的所有回调(通过then设置上去的)
        function finale() {
            for (var i = 0, len = deferreds.length; i < len; i++)
                handle(deferreds[i])
            deferreds = null
        }
    
        // 创建完,马上就调用,真直接
        //
        try { fn(resolve, reject) }
        catch (e) { reject(e) }
    }
    
    
    function Handler(onFulfilled, onRejected, resolve, reject) {
        this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
        this.onRejected = typeof onRejected === 'function' ? onRejected : null
        this.resolve = resolve
        this.reject = reject
    }
    

    index.js

    'use strict'
    
    //This file contains then/promise specific extensions to the core promise API
    
    var Promise = require('./core.js')
    var nextTick = require('./lib/next-tick')
    
    module.exports = Promise
    
    
    // 静态函数,为了将一个普通值变成promise,或者把类promise(即有then成员函数的对象)变成promise
    //
    Promise.from = function (value) {
        if (value instanceof Promise) return value
        return new Promise(function (resolve) { resolve(value) })
    }
    
    // 静态函数,去NodeJs化,把nodeJs风格的callback,变成能够返回Promise的函数。
    //
    Promise.denodeify = function (fn) {
        // 返回的是一个包装过的函数
        return function () {
            var self = this
            var args = Array.prototype.slice.call(arguments)
            // 就是返回了一个promise,不过自己写了resolver函数
            return new Promise(function (resolve, reject) {
                // 很简单,就参数最后,加一个callback
                args.push(function (err, res) {
                    if (err) reject(err)
                    else resolve(res)
                })
                fn.apply(self, args)
            })
        }
    }
    
    // 静态函数,NodeJs化,把返回promise的函数变成nodeJs风格的callback。
    //
    Promise.nodeify = function (fn) {
        // 返回的是一个包装过的函数
        return function () {
            var args = Array.prototype.slice.call(arguments)
    
            // 如果原函数最后参数是callback,就取出来
            var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null
            try {
                // 执行promise本身,但是通过成员函数nodeify挂了1个then的回调上去。
                return fn.apply(this, arguments).nodeify(callback)
            } catch (ex) {
                if (callback == null) {
                    // 有异常了,
                    return new Promise(function (resolve, reject) { reject(ex) })
                } else {
                    nextTick(function () {
                        callback(ex)
                    })
                }
            }
        }
    }
    
    // 静态函数
    //
    Promise.all = function () {
        var args = Array.prototype.slice.call(arguments.length === 1 && Array.isArray(arguments[0]) ? arguments[0] : arguments)
        // 返回一个新的Promise
        return new Promise(function (resolve, reject) {
            if (args.length === 0) return resolve([])
            var remaining = args.length
            function res(i, val) {
                try {
    
                    // 判断是不是一个promise
                    if (val && (typeof val === 'object' || typeof val === 'function')) {
                        var then = val.then
                        // 是的话,麻烦,要等一下他
                        if (typeof then === 'function') {
                            // 回调res函数(就是自身)
                            then.call(val, function (val) { res(i, val) }, reject)
                            return
                        }
                    }
    
                    // 不是,那么简单,保存它的值
                    args[i] = val
    
                    // 等到所有的值都取到了,就可以返回了
                    if (--remaining === 0) {
                        resolve(args);
                    }
                } catch (ex) {
                    reject(ex)
                }
            }
            for (var i = 0; i < args.length; i++) {
                res(i, args[i])
            }
        })
    }
    
    
    
    // 成员函数: 加入了抛异常功能,但是也不会返回promise了。
    //
    Promise.prototype.done = function (onFulfilled, onRejected) {
    
        // 先执行then,然后附加一个then,这里做了优化,没有参数就直接附加then。
        var self = arguments.length ? this.then.apply(this, arguments) : this
    
        self.then(null, function (err) {
            nextTick(function () {
                throw err
            })
        })
    }
    
    // 成员函数: nodeJs话,其实实现的很简单。
    //
    Promise.prototype.nodeify = function (callback) {
        if (callback == null) return this
    
        this.then(function (value) {
            nextTick(function () {
                callback(null, value)
            })
        }, function (err) {
            nextTick(function () {
                callback(err)
            })
        })
    }


  • 相关阅读:
    Oracle SQL语句收集
    SqlParameter In 查询
    SQL 性能优化
    Entity Framework
    【XLL API 函数】 xlfSetName
    【XLL API 函数】xlfUnregister (Form 2)
    【XLL API 函数】xlfUnregister (Form 1)
    【Excel 4.0 函数】REGISTER 的两种形式以及VBA等效语句
    【Excel 4.0 函数】REGISTER
    【Bochs 官方手册翻译】 第一章 Bochs介绍
  • 原文地址:https://www.cnblogs.com/puncha/p/3876893.html
Copyright © 2011-2022 走看看