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

发布时间:2023年12月17日

每日一题:

实现一个类,其实例可以链式调用,他有一个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

文章来源:https://blog.csdn.net/m0_46672781/article/details/135010146
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。