每日一题:实现一个类,其实例可以链式调用,他有一个sleep方法,可以sleep一段时间后再后续调用

文章介绍了两种实现类PlayBoy链式调用的方法,一种是阻塞式解决方案,使用while循环模拟睡眠;另一种是异步调用,通过Promise实现非阻塞的顺序执行。还讨论了异步队列的概念和其实现方式。
摘要由CSDN通过智能技术生成

每日一题:

实现一个类,其实例可以链式调用,他有一个sleep方法,可以sleep一段时间后再后续调用

const boy = new PlayBoy('Tom') boy.sayHi().sleep(1000).play('王者').sleep(2000).play('跳一跳') 
// 输出 
// 大家好我是Tom 
// 1s 之后 
// 我在玩王者 
// 2s 之后
// 我在玩跳一跳

方案一:思路(阻塞式解决方案)

  • 根据时间进行判断执行
  • 主要是while循环强制主线程执行此环节,while是同步代码。所以后续代码的执行会出现阻塞现象。
class PlayBoy {
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    console.log(`大家好我是${this.name}`);
    return this;
  }
  play(game) {
    console.log(`我在玩${game}`);
    return this;
  }
  sleep(time) {
    const start = new Date().getTime();
    while (new Date().getTime() < start + time) {

    }
    console.log(`${time/1000}s 之后`);
    return this 
  }
}
const boy = new PlayBoy("Tom");
boy.sayHi().sleep(1000).play("王者").sleep(2000).play("跳一跳");

方案二:思路(异步调用解决方案)

  • 主线程不阻塞
  • 虽然无法按照题目规定完成算法要求,但是也是一种无阻塞的办法实现,可以无缝
  • 主要是将sleep函数包裹成一个Promise
  • 此方案主要三实现思路过渡
class PlayBoy{
  constructor(name){
    this.name = name;
  }
  sayHi = ()=>{
    console.log(this.name);
    return this
  }
  sleep = (tiemTag)=>{
    return new Promise((resolve,reject)=>{
      setTimeout(()=>{
        resolve(this)
      },tiemTag*1000)
    })
  }
  play(doing){
    console.log(doing);
    return this;
  }
}
const boy = new PlayBoy("Tom");

boy.sayHi().sleep(2).then(async (that)=>{
  let body = that.play("打篮球");
  let result = await that.sleep(3);
  body = result.play("游泳");
  result = await that.sleep(2);
  body = result.play("回家");
});
console.log("主线程不阻塞");

思路三:(异步调用队列解决方案)

在看懂思路二的基础上,在想一种办法,即异步队列,思路二作为异步概念的强调,继承于思路二,如果将异步方法放入一个队列当中,按队列顺序进行执行。即可以实现不阻塞主线程的情况下顺序执行异步队列的方法!
demo1:(经验证此方法无法实现异步队列的顺序执行)

let queue = [new Promise((resolve)=>{
  setTimeout(()=>{
    console.log("a");
    resolve()
  },4000)
}),new Promise((resolve)=>{
  setTimeout(()=>{
    console.log("b");
    resolve()
  },3000)
})];//异步队列
async function run(){
  for(let i=0;i<queue.length;i++){
  if(typeof queue[i] === 'function'){
    queue[i]();
    }else{
      if(queue[i] instanceof Promise){
      let result = await queue[i];
      console.log(result);
      }
    }
  }
}
run();//遍历异步队列。发现无法实现顺序遍历

demo2:主线程不阻塞的顺序遍历异步队列

const createPromise = (id) => () =>{
  return new Promise(resolve=>
		setTimeout(()=>{
			console.log("promise->"+id+":"+new Date());
			resolve();
		},1000*id)
	)
} 
	
var tasks = [createPromise(1),createPromise(4),createPromise(3)];
console.log(tasks);
var doTask = tasks.reduce((prev,next)=>prev.then(()=>{
    return next()  
}),Promise.resolve());
console.log('主线程不阻塞');

这里比较难以理解的是两个地方,createPromise将返回一个匿名函数,此匿名函数如果执行将会返回一个Promise。从而达到我想要的目的;
数组方法:reduce!!!。一个被我玩坏的函数,这个函数此刻的作用就是作为启动异步队列的实现,我首先将prev只作为Promise,顺序执行过程中,通过。.then函数触发,内部下次启动任然是返回一个next()执行后的Promise!!!!。从而达到异步队列的顺序执行,


  • 理解了以上步骤,从而实现了异步方法队列的调用成功,就可以运用到此算法实例中即可。
class PlayBoy {
  constructor(name) {
    this.name = name;
    this.queue = [];
    this.games = [];
  }

  sayHi() {
    this.queue.push(() => {
      console.log(`大家好,我是${this.name}`);
    });
    return this; // 返回实例,以便链式调用
  }

  sleep(time) {
    this.queue.push(this.createPromise(time));
    return this; // 返回实例,以便链式调用
  }

  play(game) {
    this.games.push(game)
    return this; // 返回实例,以便链式调用
  }
  start() {
    this.queue.reduce((prev,next)=>prev.then(()=>{
      return next()  
    }),Promise.resolve());
  }
  createPromise = (time) => () =>{
    return new Promise(resolve=>
      setTimeout(()=>{
        console.log(this.games.shift());
        resolve();
      },1000*time)
    )
  } 
}

const boy = new PlayBoy('Gege');
boy.sayHi().sleep(2).play("唱").sleep(3).play('跳').sleep(1).play('rap').start();

按顺序时间输出:

大家好,
我是Gege


rap

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

勇敢*牛牛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值