从公众号里看到一道异步题目,花了点时间看了下,挺有意思的。
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const subFlow = createFlow([() => delay(1000).then(() => log("c"))]);
createFlow([
() => log("a"),
() => log("b"),
subFlow,
[() => delay(1000).then(() => log("d")), () => log("e")],
]).run(() => {
console.log("done");
});
// 需要按照 a,b,延迟1秒,c,延迟1秒,d,e, done 的顺序打印
按照上面的测试用例,实现 createFlow:
flow 是指一系列 effects 组成的逻辑片段。
flow 支持嵌套。
effects 的执行只需要支持串行。
原文解法:
function createFlow(effects = []) {
let sources = effects.slice().flat();
function run(callback) {
while (sources.length) {
const task = sources.shift();
const next = () => createFlow(sources).run(callback);
if (typeof task === "function") {
const res = task();
if (res?.then) {
res.then(next);
return;
}
} else if (task?.isFlow) {
task.run(next);
return;
}
}
callback?.();
}
return {
run,
isFlow: true,
};
}
如果对嵌套思路有点不明白,可以换种思路
function createFlow(effects = []) {
let sources = effects.slice().flat();
function run(callback) {
if (!sources.length) {
callback?.();
return;
}
while (sources.length > 0) {
const task = sources.shift();
if (task?.isFlow) {
let newSources = task.sources.concat(sources);
createFlow(newSources).run(callback);
break;
} else if (typeof task === "function") {
const res = task();
if (res?.then) {
res.then(() => {
createFlow(sources).run(callback);
});
break;
}
}
}
}
return {
run,
sources,
isFlow: true,
};
}
测试用例
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const subFlow = createFlow([() => delay(2000).then(() => console.log("c"))]);
createFlow([
() => console.log("a"),
() => console.log("b"),
subFlow,
[
() => delay(1000).then(() => console.log("d")),
() => delay(1000).then(() => console.log("e")),
() => delay(2000).then(() => console.log("f")),
],
]).run(() => {
console.log("done");
});