Promise实现
// 创建异步微任务 queueMicroTask(function(){})
(function () {
/* 工具类方法 */
var isPromise = function isPromise(obj) {
if ((obj !== null && typeof obj === "object") || (typeof obj === "function")) {
if (typeof obj.then === "function") {
return true;
}
}
return false;
};
var resolvePromise = function resolvePromise(promiseNew, x, resolve, reject) {
if (x === promiseNew) throw new TypeError('Chaining cycle detected for promise #<Promise>');
if (isPromise(x)) {
try {
x.then(resolve, reject);
} catch (err) {
reject(err);
}
return;
}
resolve(x);
};
/* 构造函数 */
function Promise(executor) {
if (typeof executor !== 'function') throw new TypeError('Promise resolver ' + executor + ' is not a function');
var self = this;
self.state = 'pending';
self.value = undefined;
self.onFulfilledCallbacks = [];
self.onRejectedCallbacks = [];
var change = function change(state, value) {
if (self.state !== 'pending') return;
self.state = state;
self.value = value;
setTimeout(function () {
var callbacks = self.state === 'fulfilled' ? self.onFulfilledCallbacks : self.onRejectedCallbacks;
for (var i = 0; i < callbacks.length; i++) {
var item = callbacks[i];
if (typeof item === "function") {
item(self.value);
}
}
});
};
try {
executor(function resolve(result) {
change('fulfilled', result);
}, function reject(reason) {
change('rejected', reason);
});
} catch (err) {
change('rejected', err);
}
}
/* 原型 */
Promise.prototype = {
constructor: Promise,
customize: true,
then: function (onfulfilled, onrejected) {
if (typeof onfulfilled !== "function") {
onfulfilled = function onfulfilled(value) {
return value;
};
}
if (typeof onrejected !== "function") {
onrejected = function onrejected(value) {
throw value;
};
}
var self = this,
promiseNew = null;
promiseNew = new Promise(function (resolve, reject) {
switch (self.state) {
case 'fulfilled':
setTimeout(function () {
try {
var x = onfulfilled(self.value);
resolvePromise(promiseNew, x, resolve, reject);
} catch (err) {
reject(err);
}
});
break;
case 'rejected':
setTimeout(function () {
try {
var x = onrejected(self.value);
resolvePromise(promiseNew, x, resolve, reject);
} catch (err) {
reject(err);
}
});
break;
default:
self.onFulfilledCallbacks.push(function (value) {
try {
var x = onfulfilled(value);
resolvePromise(promiseNew, x, resolve, reject);
} catch (err) {
reject(err);
}
});
self.onRejectedCallbacks.push(function (value) {
try {
var x = onrejected(value);
resolvePromise(promiseNew, x, resolve, reject);
} catch (err) {
reject(err);
}
});
}
});
return promiseNew;
},
catch: function (onrejected) {
var self = this;
return self.then(null, onrejected);
}
};
/* 对象 */
Promise.resolve = function resolve(value) {
return new Promise(function (resolve) {
resolve(value);
});
};
Promise.reject = function reject(value) {
return new Promise(function (_, reject) {
reject(value);
});
};
Promise.all = function all(promises) {
return new Promise(function (resolve, reject) {
try {
var index = 0,
len = promises.length,
results = [];
for (var i = 0; i < len; i++) {
(function (i) {
var item = promises[i];
if (!isPromise(item)) {
index++;
results[i] = item;
index === len ? resolve(results) : null;
return;
}
item.then(function (result) {
index++;
results[i] = result;
index === len ? resolve(results) : null;
}, function (reason) {
reject(reason);
});
})(i);
}
} catch (err) {
reject(err);
}
});
};
/* 暴露API */
if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = Promise;
}
if (typeof window !== 'undefined') {
window.Promise = Promise;
}
})();
简单测试
var p1 = new Promise((resolve, reject) => {
resolve(100)
})
let p2 = p1.then(function (value) {
console.log('成功', value)
return new Promise((resolve, reject) => { reject(-100) })
}, function (reason) {
console.log('失败', reason)
})
let p3 = p2.then(function (value) {
console.log('成功', value)
}, function (reason) {
console.log('失败', reason)
return 200
})
let p4 = p3.then(function (value) {
console.log('成功', value)
}, function (reason) {
console.log('失败', reason)
})
console.log('end')
包测试
1. 安装
npm install promises-aplus-tests --save-dev
2. 手写代码加入
Promise.deferred = function(){
var result = {}
result.promise = new Promise(function(resolve,reject){
result.resolve = resolve;
result.reject = reject;
})
return result;
}
3. 配置命令
{
"scripts":{
"test":"promises-aplus-tests myPromise.js"
}
}
4. 开始测试
npm run test