一道有趣的异步题

从公众号里看到一道异步题目,花了点时间看了下,挺有意思的。

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");
});

posted @ 2020-08-24 17:57  萝卜爱吃青菜  阅读(345)  评论(0)    收藏  举报