参考:Prmoises A+规范node
function Promise(fn) { var _this = this; var callback = null; this._value = null; // 存放resolve(解决)的结果 this._reason = null; // 存放reject(拒绝)的缘由 this._onResolveds = []; // 存放resolve前调用then时传入的函数onResolved(可能屡次调用then,因此是数组) this._onRejecteds = []; // 存放reject前调用catch时传入的函数onRejected(可能屡次调用catch,因此是数组) this._status = "pending"; function resolve(val) { if (_this._status !== 'pending') { // 若status已经改变为"resolved"或"rejected",回调直接在then内处理 return } _this._value = val; _this._status = "resolved"; while (callback = _this._onResolveds.shift()) { // 按注册顺序依次执行回调 callback(val) } } function reject(reason) { if (_this._status !== 'pending') { return } _this._reason = reason; _this._status = "rejected"; while (callback = _this._onRejecteds.shift()) { callback(reason) } } try { fn(resolve, reject) } catch (err) { reject(err) } }
Promise.prototype.then = function (onResolved, onRejected) { // 规范:若是 onFulfilled 不是函数,其必须被忽略 // 这里,若onResolved, onRejected 不是函数,则用一个过渡性的函数代替 onResolved = typeof onResolved === 'function'? onResolved:function(value) { return value; // 将value原封不动地传给下一个then,至关于跳过(忽略)本轮then的onResolved } onRejected = typeof onRejected === 'function'? onRejected:function(err) { throw err; // 同上,至关于跳过(忽略)本轮then的onRejected } var _this = this var promise2 // then始终返回一个Promise实例,用于链式调用。 if (_this._status === "resolved") { promise2 = new Promise(function (resolve, reject){ setTimeout(function() { // 确保onResolved 和 onRejected 方法异步执行。下面的setTimeout同理 try { var x = onResolved(_this._value) resolvePromise(promise2, x, resolve, reject) // resolvePromise内执行promise2的resolve和reject } catch (e) { reject(e) } }, 0); }) } if (_this._status === "rejected") { promise2 = new Promise(function (resolve, reject){ setTimeout(function() { try { var x = onRejected(_this._reason) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }, 0); }) } if (_this._status === "pending") { // resolve或reject前调用then的话,将回调推入队列 promise2 = new Promise(function (resolve, reject) { _this._onResolveds.push(function () { setTimeout(function() { try { var x = onResolved(_this._value) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }, 0); }); _this._onRejecteds.push(function () { setTimeout(function() { try { var x = onRejected(_this._reason) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }, 0); }); }) } return promise2 };
function resolvePromise (promise2, x, resolve, reject) { if(promise2 === x) { // 防止引用同一个promise,致使死循环 return reject(new TypeError('循环引用')); } var called = false // 防止屡次调用 if (x!== null && (typeof x ==='object' ||typeof x === 'function')) { try { let then = x.then; if (typeof then === 'function') { // x 是一个定义了 then 方法的对象或函数,即thenable then.call(x, function(y) { // 这里规范是这样说明的:这步咱们先是存储了一个指向 x.then 的引用,而后测试并调用该引用,以免屡次访问 x.then 属性。这种预防措施确保了该属性的一致性,由于其值可能在检索调用时被改变。 if (called) return // 确保resolve和reject,只执行其中一个 called = true; resolvePromise(promise2, y, resolve, reject) // 若是x是thenable,则继续调用resolvePromise,直到 onResolved/onRejected 的返回值不是 thenable }, function(err) { if (called) return called = true; reject(err); }) } else { resolve(x) // 若是 x 不属于 thenable, 则把x做为返回值. } } catch (e) { if (called) return called = true; reject(e) } } else { //普通值 resolve(x) } }
Promise.prototype.catch = function (onRejected) { return this.then(undefined, onRejected) }
Promise.resolve = function (value) { return new Promise(function (resolve, reject) { resolve(value) }) }
Promise.reject = function (reason) { return new Promise(function (resolve, reject) { reject(reason) }) }
Promise.all = function (promises) { if (!Array.isArray(promises)) { throw new TypeError('必须传入promise数组'); } var length = promises.length var values = [] return new Promise(function (resolve, reject) { function rejectHandle(reason) { reject(reason) // 只要其中一个reject,总体reject } function resolveHandle(index) { return function (value) { values[index] = value // 按传入时的顺序记录每一个promise的结果值 if (--length === 0) { // 全部子promise都resolve后,总体resolve resolve(values) } } } promises.forEach(function (item, index) { item.then(resolveHandle(index), rejectHandle) }) }) }
Promise.race = function (promises) { if (!Array.isArray(promises)) { throw new TypeError('必须传入promise数组'); } return new Promise(function (resolve, reject) { function rejectHandle(reason) { reject(reason) } function resolveHandle(value) { resolve(value) } promises.forEach(function (item) { item.then(resolveHandle, rejectHandle) }) }) }
// 无论resolved仍是rejected,都会执行,避免一样的语句须要在then()和catch()中各写一次的状况。 Promise.prototype.finally = function (callback) { return this.then(callback, callback) }
使用promises-aplus-tests
:全局安装npm i promises-aplus-tests -g
,而后命令行 promises-aplus-tests [js文件名]
进行测试npm
注意:测试前要在尾部加上下面的代码:数组
Promise.deferred = Promise.defer = function () { let deferred = {}; deferred.promise = new Promise(function (resolve, reject) { deferred.resolve = resolve; deferred.reject = reject; }); return deferred }; module.exports = Promise
测试完成后可删除promise
(function (global, factory) { if (typeof define === 'function' && define.amd) { // AMD define(factory) } else if (typeof exports === 'object' && typeof module !== 'undefined') { // CommonJS (如node) module.exports = factory() } else { // 浏览器全局变量 global.promisePolyfill = factory() } })(this, function () { 'use strict'; /* 定义Promise的代码 */ function promisePolyfill () { var global = null try { global = Function('return this')(); } catch (e) { throw new Error('全局对象不可用'); } global.Promise = Promise } return promisePolyfill })
promisePolyfill() // 注册Promise全局变量