1. 在Promise的构造函数中我们需要做哪些呢
function Promise(executor) {
if (typeof executor !== "function") {
throw new Error("Promise构造函数的参数类型为函数");
}
const that = this;
that.status = PENDING;
that.value = undefined;
that.reason = undefined;
that.onResolvedCallbacks = [];
that.onResolvedCallbacks = [];
const resolve = function (value) {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
if (that.status === PENDING) {
that.status = FULFILLED;
that.value = value;
that.onResolvedCallbacks.forEach((cb) => cb());
}
};
const reject = function (reason) {
if (that.status === PENDING) {
that.status = REJECTED;
that.reason = reason;
that.onRejectedCallbacks.forEach((cb) => cb());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
2.在原型上添加then方法,接受Promise的执行结果
const promise1 = new Promise((resolve, reject) => {})
promise1.then(
(value) => {},
(reason) => {}
)
Promise.then = function(){
....
resolvePromise(promise2, x, resolve, reject);
}
Promise.prototype.then = function (onFulfilled, onRejected) {
const that = this;
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) => v;
onRejected =
typeof onRejected === "function"
? onRejected
: (r) => {
throw r;
};
const promise2 = new Promise((resolve, reject) => {
if (that.status === PENDING) {
that.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(that.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
that.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(that.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
if (that.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(that.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (that.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(that.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
});
return promise2;
};
3. resolvePromise,处理then返回的promise状态
const resolvePromise = function (promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError("Chaining cycle detected for promise..."));
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called = false;
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
};
4. 以上Promise完成。all, race等方法部署与PromiseA+规范内容,我们后面介绍,先进行测试。
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;
5. Promise.resolve, Promise.reject
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
resolve(value);
});
};
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
};
6. catch, finally实现
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
};
Promise.prototype.finally = function (finall) {
return this.then(
(value) => {
return Promise.resolve(finall()).then(() => value);
},
(reason) => {
return Promise.resolve(finall()).then(() => {
throw reason;
});
}
);
};
7. Promise.all, Promise.race, Promise.settled
Promise.all = function (values) {
return new Promise((resolve, reject) => {
let result = [];
let times = 0;
function processMap(index, data) {
result[index] = data;
if (++times === values.length) {
resolve(result);
}
}
for (let i = 0; i < values.length; i++) {
let current = values[i];
Promise.resolve(current).then((data) => {
processMap(i, data);
}, reject);
}
});
};
Promise.race = function (values) {
return new Promise((resolve, reject) => {
values.forEach((item) => {
Promise.resolve(item).then(resolve, reject);
});
});
};
Promise.allSettled = function (values) {
return Promise((resolve, reject) => {
let times = 0;
let result = [];
function processMap(key, value) {
result[key] = value;
if (++times === values.length) {
resolve(result);
}
}
for (let index = 0; index < values.length; index++) {
const current = values[index];
Promise.resolve(current)
.then((value) => {
processMap(index, { status: "fulfilled", value });
})
.catch((reason) => {
processMap(index, { status: "rejected", reason });
});
}
});
};
8. Promise做超时处理
function withAbort(userPromise) {
let abort;
let innerPromise = new Promise((resolve, reject) => (abort = reject));
let p = Promise.race([innerPromise, userPromise]);
p.abort = abort;
return p;
}
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("ok");
}, 2000);
});
p = withAbort(p);
p.then((data) => {
console.log(data, "成功");
}).catch((reason) => {
console.log(reason);
});
setTimeout(() => {
p.abort("超时了");
}, 1000);
9. 将函数promise化
function promisify(fn) {
return function (...args) {
return new Promise((resolve, reject) => {
fn(...args, function (err, data) {
if (err) return reject(err);
resolve(data);
});
});
};
}
function promisifyAll(obj) {
for (let key in obj) {
if (typeof obj[key] == "function") {
obj[key] = promisify(obj[key]);
}
}
}
promisifyAll(fs)
10. calss形式的Promise
const PENDING = "PENGDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
const resolvePromise = function (promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError("Chaining cycle detected for promise..."));
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called = false;
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
};
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach((cb) => cb());
}
};
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((cb) => cb());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) => v;
onRejected =
typeof onRejected === "function"
? onRejected
: (r) => {
throw r;
};
const p = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(p, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(p, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(p, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(p, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
});
return p;
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(finall) {
return this.then(
(value) => {
return Promise.resolve(finall()).then(() => value);
},
(reason) => {
return Promise.resolve(finall()).then(() => {
throw reason;
});
}
);
}
}
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
resolve(value);
});
};
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
};
Promise.all = function (values) {
return new Promise((resolve, reject) => {
let result = [];
let times = 0;
function processMap(index, data) {
result[index] = data;
if (++times === values.length) {
resolve(result);
}
}
for (let i = 0; i < values.length; i++) {
let current = values[i];
Promise.resolve(current).then((data) => {
processMap(i, data);
}, reject);
}
});
};
Promise.race = function (values) {
return new Promise((resolve, reject) => {
values.forEach((item) => {
Promise.resolve(item).then(resolve, reject);
});
});
};
Promise.allSettled = function (values) {
return Promise((resolve, reject) => {
let times = 0;
let result = [];
function processMap(key, value) {
result[key] = value;
if (++times === values.length) {
resolve(result);
}
}
for (let index = 0; index < values.length; index++) {
const current = values[index];
Promise.resolve(current)
.then((value) => {
processMap(index, { status: "fulfilled", value });
})
.catch((reason) => {
processMap(index, { status: "rejected", reason });
});
}
});
};
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;