惰性计算

219 阅读1分钟

题目要求

请实现惰性计算能力lazy,具有add,tap,delay,multiply,output等方法,支持链式调用,所有方法延迟执行,只有在调用output方法的时候才执行所有方法,并输出结果。

测试用例

const work = lazy(2) // 初始化对象
  .add(2) // 原有数值增加指定数值
  .tap(console.log) // 以当前数值为参数执行回调函数
  .delay(1000) // 暂停指定时间
  .multiply(3) // 原有数值乘以指定数值

setTimeout(() => {
  work.output(); // 执行所有方法并输出最终结果
}, 1000);

console.log('start');

输出

start
(等待1s,无输出)
4
(等待1s,无输出)
12

解题思路

  1. 可以用一个tasks参数将每次需要执行的任务预存起来,在最终执行output方法的时候依次进行遍历执行;
  2. 为了支持链式调用可以每个方法都返回this;
  3. delay方法可以用无限循环同步处理或者使用定时器异步处理。

题解

同步阻塞处理方式
function lazy(initial) {
  return new LazyImpl(initial);
}

function LazyImpl(init) {
  this.num = init;
  this.tasks = [];
}
LazyImpl.prototype.add = function (addi) {
  this.tasks.push(() => {
    this.num += addi;
  })
  return this;
}

LazyImpl.prototype.tap = function (callback) {
  this.tasks.push(() => {
    if (typeof callback === 'function') {
      callback(this.num);
    }
  });
  return this;
}

LazyImpl.prototype.delay = function (delayTime) {
  this.tasks.push(() => {
    let startTime = new Date().getTime();
    let stopFlag = false;
    while (!stopFlag) {
      if (new Date().getTime() - startTime > delayTime) {
        stopFlag = true;
      }
    }
  });
  return this;
}

LazyImpl.prototype.multiply = function (mult) {
  this.tasks.push(() => {
    this.num *= mult;
  });
  return this;
}

LazyImpl.prototype.output = function () {
  for (let task of this.tasks) {
    task(this.num);
  }
  console.log(this.num);
}
异步非阻塞处理方式 其它方法实现方式一致,只有delay和output方法需要略微调整一下。
LazyImpl.prototype.delay = function (delayTime) {
  this.tasks.push(() => {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve();
      }, delayTime);
    });
  });
  return this;
}

LazyImpl.prototype.output = async function () {
  for (let task of this.tasks) {
    await task(this.num);
  }
  console.log(this.num);
}