一道有趣的异步题

从公众号里看到一道异步题目,花了点时间看了下,挺有意思的。
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  萝卜爱吃青菜  阅读(298)  评论(0编辑  收藏  举报