Promises/A+ 规范, js 实现 Promise
// @ts-ignore
export {};
// function Promise(callback) {
function Promise(this: any, callback) {
let self = this;
self.status = 'pending';
self.value = undefined;
self.onResolvedCallbacks = [];
self.onRejectedCallbacks = [];
function resolve(value) {
if (value instanceof Promise) {
// @ts-ignore
return value.then(resolve, reject);
}
setTimeout(function () {
if (self.status == 'pending') {
self.value = value;
self.status = 'resolved';
self.onResolvedCallbacks.forEach(item => item(self.value));
}
});
}
function reject(value) {
setTimeout(function () {
if (self.status == 'pending') {
self.value = value;
self.status = 'rejected';
self.onRejectedCallbacks.forEach(item => item(value));
}
});
}
try {
callback(resolve, reject);
} catch (e) {
reject(e);
}
}
//
function resolvePromise(promise2, promise, resolve, reject) {
if (promise2 === promise) {
return reject(new TypeError('循环引用'));
}
let then, called;
if (promise != null && ((typeof promise == 'object' || typeof promise === "function"))) {
try {
then = promise.then;
if (typeof then === 'function') {
then.call(promise, function (value) {
if (called)return;
called = true;
resolvePromise(promise2, value, resolve, reject);
}, function (reason) {
if (called)return;
called = true;
reject(reason);
});
} else {
resolve(promise);
}
} catch (e) {
if (called)return;
called = true;
reject(e);
}
} else {
resolve(promise);
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
return value
};
onRejected = typeof onRejected === 'function' ? onRejected : function (value) {
throw value
};
let promise2;
if (self.status == 'resolved') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let promise = onFulfilled(self.value);
resolvePromise(promise2, promise, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
if (self.status == 'rejected') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let promise = onRejected(self.value);
resolvePromise(promise2, promise, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
if (self.status == 'pending') {
promise2 = new Promise(function (resolve, reject) {
self.onResolvedCallbacks.push(function (value) {
try {
let promise = onFulfilled(value);
resolvePromise(promise2, promise, resolve, reject);
} catch (e) {
reject(e);
}
});
self.onRejectedCallbacks.push(function (value) {
try {
let promise = onRejected(value);
resolvePromise(promise2, promise, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
return promise2;
}
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
}
Promise.resolve = function (value) {
return new Promise(function (resolve, reject) {
if (typeof value !== null && typeof value === 'object' && typeof value.then === 'function') {
value.then();
} else {
resolve(value);
}
})
};
Promise.reject = function (reason) {
return new Promise(function (resolve, reject) {
reject(reason);
})
}
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
let result: any = [];
// let result = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (data) {
result[i] = data;
count += 1;
if (count == promises.length) {
resolve(result);
}
}, function (err) {
reject(err);
});
}
});
}
Promise.race = function (promises) {
return new Promise(function (resolve, reject) {
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (data) {
resolve(data);
},function (err) {
reject(err);
});
}
});
}
Promise.deferred = Promise.defer = function () {
var defer = {};
// let defer = {
// promise: null,
// resolve: null,
// reject: null,
// };
// @ts-ignore
defer.promise = new Promise(function (resolve, reject) {
// @ts-ignore
defer.resolve = resolve;
// @ts-ignore
defer.reject = reject;
})
return defer;
}
// module.exports = Promise;
https://www.cnblogs.com/xgqfrms/p/17188524.html
https://github.com/Leooman/Leooman.github.io/issues/4
https://github.com/lgwebdream/FE-Interview/issues/29#issuecomment-656644716