手写 Promise 及 then 方法
原文可可以看 https://juejin.cn/post/7040016523108286494 这篇文章,个人感觉书写的格式梳理的很好
class myPromise {
status = "pendding";
value = undefined;
onResolvedCallbacks = [];
onRejectedCallbacks = [];
constructor(exec) {
const reslove = (value) => {
const doFn = () => {
if (this.status !== "pendding") return;
this.value = value;
this.status = "resloved";
while (this.onRejectedCallbacks.length) {
this.onResolvedCallbacks.shift()();
}
};
setTimeout(doFn, 0);
};
const reject = (value) => {
const doFn = () => {
if (this.status !== "pedding") return;
this.value = value;
this.status = "rejected";
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()();
}
setTimeout(doFn, 0);
};
};
try {
exec(reslove, reject);
} catch (err) {
reject(err);
}
}
then(onReslove, onReject) {
onReslove = typeof onReslove === "function" ? onReslove : (res) => res;
onReject =
typeof onReject === "function"
? onReject
: (err) => {
throw err;
};
const newPromise = new myPromise((reslove, reject) => {
// 统一处理函数
const execFun = (fn, val) => {
try {
let res = fn(val);
if (newPromise === res) {
reject(new TypeError("回调地狱!!"));
return;
}
if (res instanceof myPromise) {
myPromise.then(reslove, reject);
} else {
reslove(res);
}
} catch (err) {
reject(err);
}
};
const success = () => {
execFun(onReslove, this.value);
};
const failed = () => {
execFun(onReject, this.value);
};
if (this.status === "pending") {
this.onResolvedCallbacks.push(success);
this.onRejectedCallbacks.push(failed);
} else if (this.status === "reslove") {
success();
} else {
failed();
}
});
return newPromise;
}
}
手写 promise.map 方法,控制并发数量限制
第一个 for 循环 limit 同步,每次执行 limit 个,当执行完当前的 promise,会进入下一个 next
function promiseMap(list, fn, limit = Infinity) {
return new Promise((reslove) => {
let ret = [];
let index = -1;
function next() {
++index;
Promise.resolve(list[index])
.then((val) => fn(val, index))
.then((res) => {
ret.push(res);
if (ret.length === arr.length) {
reslove(ret);
} else if (index < arr.length) {
next();
}
});
}
for (let i = 0; i < limit && i < list.length; i++) {
next();
}
});
}