Promise系列题目

1.使用Promise实现红绿灯交替重复亮

红灯3秒亮一次,绿灯2秒亮一次,黄灯1秒亮一次;如何让三个灯不断交替重复亮灯?

要求:用Promise实现

三个亮灯函数已经存在:

function red() {
    console.log('red');
}
function green() {
    console.log('green');
}
function yellow() {
    console.log('yellow');
}

首先题目规定了使用promise那我们先用promise的方法来实现这个红绿灯交错。
首先我们会想到使用promise的链式调用+定时器,让交通灯按照红黄绿执行。

    (function inifiteLight() {
      return Promise.resolve()
        .then(
          new Promise((resolve) => {
            red();
            setTimeout(() => {
              resolve();
            }, 1000);
          })
        )
        .then(
          new Promise((resolve) => {
            yellow();
            setTimeout(() => {
              resolve();
            }, 2000);
          })
        )
        .then(
          new Promise((resolve) => {
            green();
            setTimeout(() => {
              resolve();
            }, 3000);
          })
        )
        .then(inifiteLight());
    })();

效果还是很不错的,再把中间公共的代码抽出来,最终效果如下:

  function light(fn, time) {
      return new Promise((resolve) => {
        fn();
        setTimeout(resolve, time);
      });
    }
    (function inifiteLight() {
      return Promise.resolve()
        .then(light(red, 3000))
        .then(light(yellow, 2000))
        .then(light(green, 1000))
        .then(inifiteLight());
    })();

除此之外,我们思考,如果不使用promise,那么怎么让这三个灯按顺序执行并且无限循环呢?
可能我们首先会想到使用setInterval,是的,我们来尝试下~
正确用例✅:

    setInterval(() => {
      setTimeout(() => {
        red();
      }, 1000);
      setTimeout(() => {
        yellow();
      }, 2000);
      setTimeout(() => {
        green();
      }, 3000);
    }, 3000);

实际上果然可行…那么接着我们把代码优化下:

   const light = (fn, time) => {
      setTimeout(fn, time);
    };
    setInterval(() => {
      light(red, 1000);
      light(yellow, 2000);
      light(green, 3000);
    }, 3000);

但是注意,setInterval的执行时间,一定要和setTimeout等待时间最长任务时间一致,比如:
如果我们把setInterval的执行时间设置为1000,则每1000ms会重新启一个定时器再重复执行,导致最终输出的log位置错乱,也就不能按想要的顺序执行了。
错误用例❌:

  setInterval(() => {
      setTimeout(() => {
        red();
      }, 1000);
      setTimeout(() => {
        yellow();
      }, 2000);
      setTimeout(() => {
        green();
      }, 3000);
    }, 1000);

以上输出会顺序错乱~

那么问题来了,既然每次执行setInterval都会重新创建新的,当执行次数过多之后,肯定会造成内存泄漏。
那么我们如何优化呢?
我们可以想到2个方案:

  • 控制setInterval执行后销毁,再去创建一个新的,保证永远只有一个setInterval在执行。
  • 使用setTimeout的链式调用。

控制setInterval执行后销毁,第一个方案宣告失败
发生了预期之外的错误输出,我们的预期是red、yellow、green

  function inifiteLight() {
      let timer = setInterval(() => {
        light(red, 1000);
        light(yellow, 2000);
        light(green, 3000);
        if (timer) {
          clearInterval(timer);
          inifiteLight();
        }
      }, 1000);
    }
    inifiteLight();

在这里插入图片描述
使用setTimeout的链式调用,第二个方案可行
上代码,有点类似于promise的链式调用

    function red() {
      console.log("red");
    }
    function green() {
      console.log("green");
    }
    function yellow() {
      console.log("yellow");
    }

    function inifiteLight() {
      setTimeout(() => {
        red();
        setTimeout(() => {
          yellow();
          setTimeout(() => {
            green();
            setTimeout(inifiteLight);
          }, 1000);
        }, 1000);
      }, 1000);
    }
    inifiteLight();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七安安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值