今天研究了下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) }) }) }