面试题
实现一个带并发限制的异步调度器
比如保证同时运行的任务最多有两个
const timeout = (time) =>
new Promise((resolve) => {
setTimeout(resolve, time);
});
const scheduler = new Scheduler();
const addTask = (time, order) => {
scheduler.add(() => timeout(time)).then(() => console.log(order));
};
addTask(1000, "1");
addTask(500, "2");
addTask(300, "3");
addTask(400, "4");
// output: 2 3 1 4
// 一开始,1、2两个任务进入队列
// 500ms时,2完成,输出2,任务3进队
// 800ms时,3完成,输出3,任务4进队
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4
class Scheduler {
constructor(count) {
this.count = 2;
this.queue = [];
this.run = [];
}
add(task) {
this.queue.push(task);
return this.schedule();
}
schedule() {
if (this.run.length < this.count && this.queue.length) {
const task = this.queue.shift();
const promise = task().then(() => {
this.run.splice(this.run.indexOf(promise), 1);
});
this.run.push(promise);
return promise;
} else {
return Promise.race(this.run).then(() => this.schedule());
}
}
}
取消/限时
参考 https://cloud.tencent.com/developer/article/1785993 这里的取消指的是对结果不再处理,代码仍会执行,原理类似于取消请求
var timeLimit = function (fn, t) {
const limit = new Promise((resolve, reject) => {
// 埋雷
setTimeout(() => {
reject("Time Limit Exceeded");
}, t);
});
return async function (...args) {
// 时间到就炸雷
const result = await Promise.race([fn(...args), limit]);
console.log(result);
return result;
};
};
结合 AbortController/ajax.abort 或 clearTimeout 取消异步请求或未执行的定时器
使用 Promise 实现每隔 1 秒输出 1,2,3
reduce + promise
const arr = [1, 2, 3];
arr.reduce((p, x) => {
return p.then(() => {
return new Promise((r) => {
setTimeout(() => r(console.log(x)), 1000);
});
});
}, Promise.resolve());
async
let arr = [1, 2, 3, 4];
async function sleep() {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 1000);
});
}
(async () => {
for (let i in arr) {
await sleep();
console.log(arr[i]);
}
})();
mergePromise
把传进去的 promise 数组按顺序先后执行
function mergePromise(ajaxArray) {
// 存放每个ajax的结果
const data = [];
let promise = Promise.resolve();
ajaxArray.forEach((ajax) => {
promise = promise.then(ajax).then((res) => {
data.push(res);
return data;
});
});
return promise;
}
for...of + await
const mergePromise = (ajaxArray) => {
return new Promise(async function (resolve) {
let data = [];
for (let it of ajaxArray) {
let tmp = await it();
data.push(tmp);
}
resolve(data);
});
};
当然,也可以用 reduce 实现
使用 Promise 实现红绿灯交替重复亮
function red() {
console.log("red");
}
function green() {
console.log("green");
}
function yellow() {
console.log("yellow");
}
const run = () =>
Promise.resolve()
.then(() => wrap(red, 5))
.then(() => wrap(green, 2))
.then(() => wrap(yellow, 1))
.then(() => run());
function wrap(fn, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
fn();
resolve();
}, time * 1000);
});
}
run();