Sunny-117 / js-challenges

✨✨✨ Challenge your JavaScript programming limits step by step
https://juejin.cn/column/7244788137410560055
2k stars 236 forks source link

交通灯 #164

Open Sunny-117 opened 1 year ago

LevyEvans-s commented 1 year ago

解法一:回调方式实现

@Author: 北方银时 @blog: https://juejin.cn/user/602954369606199

// 模拟红灯亮
function red() {
  console.log('red')
}

//模拟绿灯亮
function green() {
  console.log('green')
}

//模拟黄灯亮
function yellow() {
  console.log('yellow')
}

const task = (timer, light, callback) => {
  setTimeout(() => {
    if (light === 'red') {
      red()
    } else if (light === 'green') {
      green()
    } else if (light === 'yellow') {
      yellow()
    }
    //灯亮完之后执行回调
    callback()
  }, timer)
}

//存在bug: 代码只完成了一次交替亮灯
// task(3000, 'red', () => {
//   task(1000, 'green', () => {
//     task(2000, 'yellow', Function.prototype)
//   })
// })

//解决方案:通过递归让亮灯的一个周期无限循环
const step = () => {
  task(3000, 'red', () => {
    task(1000, 'green', () => {
      task(2000, 'yellow', step)
    })
  })
}

step()
LevyEvans-s commented 1 year ago

解法二:Promise方案

@author: 北方银时 @blog: https://juejin.cn/user/602954369606199

// 模拟红灯亮
function red() {
  console.log('red')
}

//模拟绿灯亮
function green() {
  console.log('green')
}

//模拟黄灯亮
function yellow() {
  console.log('yellow')
}

const task = (timer, light) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (light === 'red') {
        red()
      } else if (light === 'green') {
        green()
      } else if (light === 'yellow') {
        yellow()
      }
      resolve()
    }, timer)
  })
}

const step = () => {
  task(3000, 'red')
    .then(() => task(1000, 'green'))
    .then(() => task(2000, 'yellow'))
    .then(step)
}

step()
LevyEvans-s commented 1 year ago

解法三: Async/await 大杀器

@author: 北方银时 @blog: https://juejin.cn/user/602954369606199

function red() {
  console.log('red')
}

function green() {
  console.log('green')
}

function yellow() {
  console.log('yellow')
}

const task = (timer, light) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (light === 'red') {
        red()
      } else if (light === 'green') {
        green()
      } else if (light === 'yellow') {
        yellow()
      }
      resolve()
    }, timer)
  })
}

const taskRunner = async () => {
  await task(3000, 'red')
  await task(1000, 'green')
  await task(2000, 'yellow')
  taskRunner()
}

taskRunner()
Tsuizen commented 1 year ago

timer为什么不统一设置1000

SecurityILiu commented 1 year ago

注意题目,红绿灯

------------------ 原始邮件 ------------------ 发件人: @.>; 发送时间: 2023年2月7日(星期二) 下午3:18 收件人: @.>; 抄送: @.>; @.>; 主题: Re: [Sunny-117/js-challenges] 交通灯 (Issue #164)

timer为什么不统一设置1000

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

akira-cn commented 1 year ago

解法三: Async/await 大杀器

@author: 北方银时 @blog: https://juejin.cn/user/602954369606199

function red() {
  console.log('red')
}

function green() {
  console.log('green')
}

function yellow() {
  console.log('yellow')
}

const task = (timer, light) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (light === 'red') {
        red()
      } else if (light === 'green') {
        green()
      } else if (light === 'yellow') {
        yellow()
      }
      resolve()
    }, timer)
  })
}

const taskRunner = async () => {
  await task(3000, 'red')
  await task(1000, 'green')
  await task(2000, 'yellow')
  taskRunner()
}

taskRunner()

既然用了异步语法,不需要再用递归,直接用循环更优雅:

const taskRunner = async () => {
    while(1) {
        await task(3000, 'red')
        await task(1000, 'green')
        await task(2000, 'yellow')
    }
}
SecurityILiu commented 1 year ago

js是单线程,这样会卡死的

------------------ 原始邮件 ------------------ 发件人: @.>; 发送时间: 2023年2月9日(星期四) 上午10:59 收件人: @.>; 抄送: @.>; @.>; 主题: Re: [Sunny-117/js-challenges] 交通灯 (Issue #164)

解法三: Async/await 大杀器

@author: 北方银时 @blog: https://juejin.cn/user/602954369606199 function red() { console.log('red') } function green() { console.log('green') } function yellow() { console.log('yellow') } const task = (timer, light) => { return new Promise((resolve, reject) => { setTimeout(() => { if (light === 'red') { red() } else if (light === 'green') { green() } else if (light === 'yellow') { yellow() } resolve() }, timer) }) } const taskRunner = async () => { await task(3000, 'red') await task(1000, 'green') await task(2000, 'yellow') taskRunner() } taskRunner()

既然用了异步语法,不需要再用递归,直接用循环更优雅: const taskRunner = async () => { while(1) { await task(3000, 'red') await task(1000, 'green') await task(2000, 'yellow') } }

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

akira-cn commented 1 year ago

js是单线程,这样会卡死的 ------------------ 原始邮件 ------------------ 发件人: @.>; 发送时间: 2023年2月9日(星期四) 上午10:59 收件人: @.>; 抄送: @.>; @.>; 主题: Re: [Sunny-117/js-challenges] 交通灯 (Issue #164) 解法三: Async/await 大杀器 @author: 北方银时 @blog: https://juejin.cn/user/602954369606199 function red() { console.log('red') } function green() { console.log('green') } function yellow() { console.log('yellow') } const task = (timer, light) => { return new Promise((resolve, reject) => { setTimeout(() => { if (light === 'red') { red() } else if (light === 'green') { green() } else if (light === 'yellow') { yellow() } resolve() }, timer) }) } const taskRunner = async () => { await task(3000, 'red') await task(1000, 'green') await task(2000, 'yellow') taskRunner() } taskRunner() 既然用了异步语法,不需要再用递归,直接用循环更优雅: const taskRunner = async () => { while(1) { await task(3000, 'red') await task(1000, 'green') await task(2000, 'yellow') } } — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

卡不死的,因为循环里面用了异步,你直接在浏览器里面跑一下就知道了。

Digoler commented 1 year ago
function red() {
    console.log('red')
}

function green() {
    console.log('green')
}

function yellow() {
    console.log('yellow')
}
// 要求:红灯3秒亮一次,黄灯2秒亮一次,绿灯1秒亮一次。
const light = function(timer, cb) {
    return new Promise(resolve => {
        setTimeout(() => {
            cb()
            resolve()
        }, timer);
    })
}

const step = function() {
    Promise.resolve().then(() => {
        return light(3000, red)
    }).then(() => {
        return light(2000, green)
    }).then(() => {
        return light(1000, yellow)
    }).then(() => {
        return step()
    })
}

step()
xun-zi commented 1 year ago
function red() {
        console.log('red')
    }
    function green() {
        console.log('green')
    }
    function blue() {
        console.log('blue')
    }

    function sleep(timer) {
        return new Promise((resovle, reject) => {
            setTimeout(resovle, 3000);
        })
    }

    async function task() {
        while (1) {
            await sleep(1000);
            red();
            await sleep(2000);
            blue();
            await sleep(3000);
            green();
        }
    }
    task()
Banks1y commented 1 year ago
//promise then
function Traficlight(light,timer){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log(light);
            resolve()
        },timer)
    })
}
const step = ()=>{
    Traficlight('red',3000).then(()=>Traficlight('yellow',2000)).then(()=>Traficlight('green',1000)).then(step)
}
step()
//async await
function Traficlight(light,timer){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log(light);
            resolve()
        },timer)
    })
}
const step = async()=>{
    await Traficlight('red',3000)
    await Traficlight('yellow',2000)
    await Traficlight('green',1000)
    step()
}
step()
kezoo commented 1 year ago
function simTrafficSignal () {
  const  list = [
    {name: 'r', offset: 3, bg: 'pink'},
    {name: 'g', offset: 2, bg: 'cyan'},
    {name: 'y', offset: 1, bg: 'orange'},
  ]
  const cls = `tfSn`
  let el = document.querySelector('.'+cls)
  if (!el) {
    el = document.createElement('div')
    el.className = cls
    el.style.width = `1rem`
    el.style.height = `1rem`
    document.body.appendChild(el)
  }
  const fn = (idx) => {
    const l = list[idx] || list[0]
    if (!list[idx]) { idx = 0 }
    el.style.backgroundColor = l.bg;
    setTimeout(() => fn(++idx), l.offset*1000)
  }
  fn(0)
}
HuangDaohong commented 1 year ago
// 循环打印红灯3秒,绿灯1秒,黄灯2秒,不断交替重复亮灯
function light (name, timer) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(name);
      resolve();
    }, timer);
  });
}

const lightList = [
  { name: 'red', timer: 3000 },
  { name: 'green', timer: 1000 },
  { name: 'yellow', timer: 2000 }
];

async function runLights () {
  // await light('red', 3000);
  // await light('green', 1000);
  // await light('yellow', 2000);
  for (let i = 0; i < lightList.length; i++) {
    const { name, timer } = lightList[i];
    await light(name, timer);
  }
  runLights();
}
runLights();
zhongqiaoshan commented 1 year ago

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

  const list = {
    green: green,
    yellow: yellow,
    red: red,
  };

  const stak = (fun, time) => {
    return new Promise((resolve, rejected) => {
      setTimeout(() => {
        list[fun]();
        resolve();
      }, time);
    });
  };

  const step = async () => {
    await stak("red", 3000);
    await stak("yellow", 3000);
    await stak("green", 3000);
  };
  step();
wangjs-jacky commented 12 months ago

基于 tapable 思想:红绿灯问题可转化为异步串行 + 循环结构构造

/* 方案一:封装 Promise 列表 */
const light = (callback, seconds = 500) => {
  return () => {
    return new Promise(resolve => {
      setTimeout(() => {
        callback();
        resolve();
      }, seconds);
    })
  }
}

const tasks = [light(red), light(yellow), light(green)];

/* 异步串行写法
   a().then(()=>b()).then(()=>c())
      .then(()=>console.log("串执行结束"))
      .catch(()=> console.log("串行执行报错"))
*/
const taskRun = () => {
  const [first, ...otherTasks] = tasks;
  return new Promise((resolve, reject) => {
    otherTasks.reduce((pre, cur) => {
      return pre.then(() => cur())
    }, first())
      .then(() => {
        /* taskRun(); */
        resolve();
      })
  })
}

/* 包裹 taskRun 为递归 */
const loopTask = async () => {
  await taskRun().then(() => console.log("结束"))
  loopTask();
}

/* 启动循环 */
loopTask();
wangjs-jacky commented 12 months ago

方案二:基于 koa 函数的 compose 思想

/* 构造延时 */
const light = (cb, delay = 1000) => {
  return (next) => setTimeout(() => {
    cb();
    /* 当前函数执行后,触发 next 函数 */
    next();
  }, delay)
}

const tasks = [light(red), light(yellow), light(green)];

const compose = (tasks) => {
  const dispatch = (i) => {
    /* 移动指针至头部 */
    if (i === tasks.length) {
      i = 0;
    }
    /* 取出下一个任务 */
    const next = () => dispatch(i + 1)
    /* 取出当前任务 */
    const curTask = tasks[i];
    return curTask(next);
  }
  dispatch(0);
}
compose(tasks);
yuan0221 commented 8 months ago
function sleep(time) {
  return new Promise(resolve => {
    setTimeout(resolve, time);
  })
}

async function go() {
  green();
  await sleep(1000);
  yellow();
  await sleep(300);
  red();
  await sleep(500);
  go();
}

go();
shenxiang11 commented 7 months ago

很多题,我都不知道题是什么,就光有一个标题,全靠自己查吗 😭

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

jianxingyao commented 4 weeks ago
// promise 红绿灯
const task = (time, type) => {
    return new Promise(res => {
        setTimeout(() => {
            if (type === 'green') {
                console.log('绿灯')
            }
            else if (type === 'yellow') {
                console.log('黄灯')
            }
            else if (type === 'red') {
                console.log('红灯')
            }
            res()
        }, time);
    })
}

async function run(time, start = true) {
    if (start) {
        console.log('开始 绿灯')
        start = false
    }else{
        await task(time, 'green')
    }
    task(time, 'yellow').then(() => task(time, 'red')).then(() => run(time, start))
}
run(300)