顺序执行功能?不确定如何精确描述问题

时间:2018-09-21 02:26:52

标签: javascript

我试图解决这个问题;但莫名其妙地停留在中间。问题是要实现一个函数$ do(),该函数可以接受任意数量的函数并按调用顺序执行它们。 在特定示例中,在700毫秒内打印a,在200毫秒内打印b,然后在100毫秒内打印c。挑战部分是虽然c应该首先打印,但是在a和b被调用之后在$ do()之后被调用。 我的实现如下,几乎可以正常工作,但是由于某种原因无法打印c。需要帮助。非常感谢。

const a = (cb) => {
    setTimeout(() => {
        cb();
        console.log('a', 700);
    }, 700);
};

const b = (cb) => {
    setTimeout(() => {
        cb();
        console.log('b', 200);
    }, 200);
};


const c = (cb) => {
    setTimeout(() => {
        cb();
        console.log('c', 100);
    }, 100);
};

const stores = [];
let running = false;

function $do() {
    const cbs = Array.prototype.slice.call(arguments);
    stores.push(cbs);
    let i = 0;

    while (stores.length > 0 && !running) {
        let head = stores.shift();
        running = i < head.length;

        head.forEach((cb) => {
            cb(() => {
                i++;
                running = i < head.length;
                console.log(running);
            });
        });
    }
}

$do(a, b);
$do(c);

2 个答案:

答案 0 :(得分:2)

此解决方案使用闭包和Promise.all()来等待$do()的每个先前挂起的调用完成,然后再调用当前调用中提供的每个函数。

这意味着ca都必须回叫之前,才会调用b

const delay = (name, ms) => cb => {
  setTimeout(() => {
    cb()
    console.log(name, ms)
  }, ms)
}

const a = delay('a', 700)
const b = delay('b', 200)
const c = delay('c', 100)

const $do = (() => {
  let done = Promise.resolve()

  return (...fns) => {
    done = done.then(
      () => Promise.all(fns.map(fn => new Promise(fn)))
    )
  }
})()

$do(a, b)
$do(c)

答案 1 :(得分:0)

在下面使用IIFE只是为了避免不必要地污染全局名称空间

我不确定的一件事是将数组推入商店-如果没有“处理”,数组将最终结束

[[a, b],[c]]

而您所需的处理将是a,然后是b,然后是c-这样存储就可以很容易地

[a, b, c]

顺便说一下,下面的代码是做什么的

const a = (cb) => {
    setTimeout(() => {
        cb();
        console.log('a', 700);
    }, 700);
};

const b = (cb) => {
    setTimeout(() => {
        cb();
        console.log('b', 200);
    }, 200);
};


const c = (cb) => {
    setTimeout(() => {
        cb();
        console.log('c', 100);
    }, 100);
};
// NOTE: I only use the IIFE to not polute GLOBAL namespace with stores and running variables
const $do = (() => {
    const stores = [];
    let running = false;

    let process = () => {
        const cb = stores.shift();
        cb(() => {
            running = !!stores.length;
            if (running) {
                process();
            }
        });
    };
    return (...cbs) => {
        stores.push(...cbs);
        if (!running) {
            running = true;
            process();
        }
    };
})();

$do(a, b);
$do(c);