源码的主要实现原理:
1.status三种状态的控制;
- then驱动式递归返回promise实现链式调用
- onFulfilled 和 onRejected 必须是setTimeOut模拟异步的确保handle时时异步的,
(更具有标准性,保证每个promise.then执行都是异步性,会损可忽略的性能)
实际上源码的handle异步处理比setTimeOut等级更高
var Promise = (function () {
function Promise(executor) {
// 初始状态
this.state = 'pending';
// 成功后必须有一个终值
this.value = undefined;
// 失败后必须有一个据因
this.reason = undefined;
// 成功时的回调函数集
this.onFulfilledSucc = [];
// 失败的回调函数集
this.onRejectedFail = [];
var _this = this;
var resolve = function (value) {
if (_this.state === 'pending') {
_this.state = 'fulfilled'
_this.value = value;
// 执行回调函数集中的函数
_this.onFulfilledSucc.forEach(function (fuc) {
fuc();
});
}
}
var reject = function (reason) {
if (_this.state === 'pending') {
_this.state = 'rejected';
_this.reason = reason;
// 执行回调函数集中的函数
_this.onRejectedFail.forEach(function (fuc) {
fuc();
});
}
}
// executor执行发生错,则直接reject
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
function resolvePromise(promise2, x, resolve, reject) {
// 如果 x === promise2,则会造成循环引用
if (x === promise2) {
return reject(new TypeError('Chaining cycle detected for promise!'))
}
// 防止多次调用
var called;
// x不是null 且x是对象或者函数
if (x != null && (typeof x === 'object') || (typeof x === 'function')) {
try {
// 把 x.then 赋值给 then
var then = x.then;
// 如果then是函数,就默认是x是promise了
if (typeof then === 'function') {
// 如果 then 是函数,将 x 作为函数的作用域 this 调用之。
then.call(x, function (y) {
// 成功和失败只能调用一个
if (called) return;
called = true;
// 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
resolvePromise(promise2, y, resolve, reject);
}, function (r) {
if (called) return;
called = true;
// 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
reject(r);
});
} else {
resolve(x);
}
} catch (e) {
// 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
if (called) return;
called = true;
reject(e);
}
} else {
// 如果 x 不为对象或者函数,以 x 为参数执行 promise
resolve(x);
}
}
// 原型方法
Promise.prototype.then = function (onFulfilled, onRejected) {
// 如果onFulfilled不是函数,其必须被忽略
onFulfilled = typeof onFulfilled === 'function'
? onFulfilled : function (value) { return value };
// 如果onRejected不是函数,其必须被忽略
onRejected = typeof onRejected === 'function'
? onRejected : function (err) { throw err };
var _this = this;
var promise2 = new Promise(function (resolve, reject) {
if (_this.state === 'fulfilled') {
// 规定onFulfilled或onRejected不能同步被调用,必须异步调用。
setTimeout(function () {
try {
var x = onFulfilled(_this.value);
// 根据x的值修改promise2的状态
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (_this.state === 'rejected') {
setTimeout(function () {
try {
var x = onRejected(_this.reason);
// 根据x的值修改promise2的状态
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (_this.state === 'pending') {
// onFulfilled传入到成功时的回调函数集
_this.onFulfilledSucc.push(function () {
setTimeout(function () {
try {
var x = onFulfilled(_this.value);
// 根据x的值修改promise2的状态
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
// onRejectedFail传入到失败时的回调函数集
_this.onRejectedFail.push(function () {
setTimeout(function () {
try {
var x = onRejected(_this.reason);
// 根据x的值修改promise2的状态
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
});
}
});
return promise2;
}
// Promise.prototype.catch方法是.then(null, rejection)或
// .then(undefined, rejection)的别名,用于指定发生错误时的回调函数。
Promise.prototype.catch = function (fn) {
return this.then(null, fn);
}
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) {
return new Promise(function (resolve, reject) {
var promiseLen = promises.length;
var resolvedCounter = 0;
var resolvedValues = new Array(promiseLen);
for (var i = 0; i < promiseLen; i++) {
(function (i) {
Promise.resolve(promises[i]).then(function (value) {
resolvedCounter++;
resolvedValues[i] = value;
if (resolvedCounter == promiseLen) {
return resolve(resolvedValues);
}
}, function (reason) {
return reject(reason);
});
})(i);
}
});
}
Promise.race = function (promises) {
return new Promise(function (resolve, reject) {
for (var i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(function (value) {
return resolve(value);
}, function (reason) {
return reject(reason);
});
}
});
}
return Promise;
})();
Promise.defer = Promise.deferred = function () {
let dfd = {}
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;
实现多个异步任务的加载,限制并行加载的数量,最后返回所有加载的结果
const waits = [3000, 4000, 200, 8000, 10000, 2000, 1000, 5000]
function loadSync(wait) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(wait)
}, wait)
})
};
function limitLoad(urls, handler, limit) {
const sequence = [].concat(urls)
let promises = [];
const result = [];
promises = sequence.splice(0, limit).map((url, index) => {
return handler(url).then((d) => {
result.push(d);
return index
});
});
return sequence.reduce((last, url, currentIndex) => {
return last.then(() => {
return Promise.race(promises)
}).catch(err => {
console.error(err)
}).then((res) => {
promises[res] = handler(sequence[currentIndex]).then((d) => { result.push(d); return res });
})
}, Promise.resolve()).then(() => {
// 假设有8个异步,实际才执行raise5次得到Top的结果,需要将最后三个执行完再返回总结果
return Promise.all(promises).then(() => {
return Promise.resolve(result)
})
})
}
limitLoad(waits, loadSync, 3).then(d => {
console.log(d, "data")
})