为什么链中的所有方法同时执行?

Why all methods in chain executed at the same time?

为什么链中的所有方法同时执行?我将方法包装在 setTimeout 中。我做错了什么?

我知道如何使用 promise 来做到这一点,但我正在学习链接技术。

const delay = function delay(func) {
  return function(...args) {
    setTimeout(() => {
      return func.apply(this, [...args]);
    }, 2000);
    return this;
  };
}

class TimePopup {

  constructor() {
    this.firstMethod = delay(this.firstMethod);
    this.secondMethod = delay(this.secondMethod);
    this.thirdMethod = delay(this.thirdMethod);
    console.log('This is the constructor');
  }

  firstMethod(val) {
    console.log('This is the First Method', val);
  }

  secondMethod(val) {
    console.log('This is the Second Method', val);
  }

  thirdMethod(val) {
    console.log('This is the Third Method', val);
  }
}

new TimePopup()
  .firstMethod(1)
  .secondMethod(2)
  .thirdMethod(3);

您遇到的问题是 delay 没有安排事情 运行 相对于彼此 。每件事都在它被调用的时间准确延迟,因此 new TimePopup().firstMethod(1).secondMethod(2).thirdMethod(3); 将同时调用所有三个方法,并且每个方法相对于调用时间延迟相同的时间量。然后两秒后三个都开火。

相反,您需要按顺序处理它们。类似于 ,您可以使用创建一个承诺队列来处理序列。每个方法 添加到链 而不是在执行之前有一个延迟:

const wait = ms => () =>
  new Promise(resolve => setTimeout(resolve, ms));
  
let queue = Promise.resolve();
  
function delay(func) {
  return function(...args) {
    queue = queue
      .then(wait(2000))
      .then(() => func.apply(this, [...args]));
    return this;
  };
}

class TimePopup {

  constructor() {
    this.firstMethod = delay(this.firstMethod);
    this.secondMethod = delay(this.secondMethod);
    this.thirdMethod = delay(this.thirdMethod);
    console.log('This is the constructor');
  }

  firstMethod(val) {
    console.log('This is the First Method', val);
  }

  secondMethod(val) {
    console.log('This is the Second Method', val);
  }

  thirdMethod(val) {
    console.log('This is the Third Method', val);
  }
}

new TimePopup()
  .firstMethod(1)
  .secondMethod(2)
  .thirdMethod(3);

一种更可重用的方法是按需创建 delay 函数,这样您就可以为不同的任务设置不同的队列。这看起来像这样:

const delayMaker = delayBetween => {
  let queue = Promise.resolve();

  return function delay(func) {
    return function(...args) {
      queue = queue
        .then(wait(delayBetween))
        .then(() => func.apply(this, [...args]));
      return this;
    };
  }
}

/* ... */

const delay = delayMaker(2000);

const wait = ms => () =>
  new Promise(resolve => setTimeout(resolve, ms));

const delayMaker = delayBetween => {
  let queue = Promise.resolve();

  return function delay(func) {
    return function(...args) {
      queue = queue
        .then(wait(delayBetween))
        .then(() => func.apply(this, [...args]));
      return this;
    };
  }
}

class TimePopup {

  constructor() {
    const delay = delayMaker(2000);
    
    this.firstMethod = delay(this.firstMethod);
    this.secondMethod = delay(this.secondMethod);
    this.thirdMethod = delay(this.thirdMethod);
    console.log('This is the constructor');
  }

  firstMethod(val) {
    console.log('This is the First Method', val);
  }

  secondMethod(val) {
    console.log('This is the Second Method', val);
  }

  thirdMethod(val) {
    console.log('This is the Third Method', val);
  }
}

new TimePopup()
  .firstMethod(1)
  .secondMethod(2)
  .thirdMethod(3);

在 pre-promise 时代,一种流行的方法是传递一个 next 函数,该函数应该将下一个排队的任务从堆栈中移出并 运行 它。一个简化的例子:

class App {
    funcs = [];

    use(func) {
        this.funcs.push(func)
        return this
    }

    next() {
        if (this.funcs.length)
            this.funcs.shift()(this.next.bind(this))
    }
}

//

function delay(func) {
    return function (next) {
        setTimeout(() => {
            func();
            next();
        }, 1000);
    }
}

//

(new App())
    .use(delay(() => console.log(1)))
    .use(delay(() => console.log(2)))
    .use(delay(() => console.log(3)))
    .next()