Daily-Interview-Question
Daily-Interview-Question copied to clipboard
第 56 题:要求设计 LazyMan 类,实现以下功能。
LazyMan('Tony');
// Hi I am Tony
LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
Answer
class LazyManClass {
constructor(name) {
this.taskList = [];
this.name = name;
console.log(`Hi I am ${this.name}`);
setTimeout(() => {
this.next();
}, 0);
}
eat (name) {
var that = this;
var fn = (function (n) {
return function () {
console.log(`I am eating ${n}`)
that.next();
}
})(name);
this.taskList.push(fn);
return this;
}
sleepFirst (time) {
var that = this;
var fn = (function (t) {
return function () {
setTimeout(() => {
console.log(`等待了${t}秒...`)
that.next();
}, t * 1000);
}
})(time);
this.taskList.unshift(fn);
return this;
}
sleep (time) {
var that = this
var fn = (function (t) {
return function () {
setTimeout(() => {
console.log(`等待了${t}秒...`)
that.next();
}, t * 1000);
}
})(time);
this.taskList.push(fn);
return this;
}
next () {
var fn = this.taskList.shift();
fn && fn();
}
}
function LazyMan(name) {
return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food');
class LazyManClass {
constructor(name) {
this.name = name
this.queue = []
console.log(`Hi I am ${name}`)
setTimeout(() => {
this.next()
},0)
}
sleepFirst(time) {
const fn = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.next()
}, time)
}
this.queue.unshift(fn)
return this
}
sleep(time) {
const fn = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.next()
},time)
}
this.queue.push(fn)
return this
}
eat(food) {
const fn = () => {
console.log(`I am eating ${food}`)
this.next()
}
this.queue.push(fn)
return this
}
next() {
const fn = this.queue.shift()
fn && fn()
}
}
function LazyMan(name) {
return new LazyManClass(name)
}
function LazyMan(name){
var lazy = new Lazy(name);
lazy.init();
return lazy;
}
function Lazy(name){
this.name = name;
this.fns = [];
this.init = function(){
var _this = this;
_this.print("I am "+this.name);
setTimeout(function(){
_this.next();
}, 0);
};
this.eat = function(food){
var _this = this;
_this.fns.push(function(){
_this.print("I am eating "+food);
_this.next();
});
return this;
};
this.sleep= function(time){
var _this = this;
_this.fns.push(function(){
setTimeout(function(){
_this.print("等待了" + time + "秒");
_this.next();
}, 1000*time);
});
return this;
};
this.sleepFirst = function(time){
var _this = this;
_this.fns.unshift(function(){
setTimeout(function(){
_this.print("等待了" + time + "秒");
_this.next();
}, 1000*time)
});
return this;
};
this.print = function(something){
console.log(something);
};
this.next = function(){
this.fns.length>0 && this.fns.shift()();
};
}
function LazyMan (name) { class Man { constructor (name) { this._queues = [] console.log(`Hi I am ${name}`) Promise.resolve().then(() => { this.next() }) return this } _sleep = (time) => { return new Promise(resolve => setTimeout(resolve, time * 1000)) } eat (type) { this._queues.push(() => { console.log(`I am eating ${type}`) this.next(); }) return this } sleepFirst (time) { this._queues.unshift(() => { this._sleep(time).then(() => { console.log(`等待了${time}秒`) this.next() }) }) return this } sleep (time) { this._queues.push(() => { this._sleep(time).then(() => { console.log(`等待了${time}秒`) this.next() }) }) return this } next () { const fn = this._queues.shift(); fn && fn() } } return new Man(name) } LazyMan('Tom'); LazyMan('Tom').sleep(10).eat('lunch') LazyMan('Tom').eat('lunch').sleep(10).eat('dinner') LazyMan('Tom').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
class LazyMan {
constructor(name) {
this.task = [];
this.task.push(
() => {
console.log(`My name is ${name}`);
this.next();
}
)
setTimeout(() => { this.next() })
}
eat(val) {
this.task.push(
() => {
console.log(`吃 ${val}`);
this.next();
}
)
return this;
}
sleep(sec) {
this.task.push(
() => {
setTimeout(() => {
console.log(`睡 ${sec} 秒`);
this.next();
}, sec * 1000);
}
)
return this;
}
next() {
let fn = this.task.shift();
fn && fn();
}
}
let lazyCzh = new LazyMan('czh');
lazyCzh.eat('apple').eat('banana').sleep(3).eat('orange');
Proxy 版本
function LazyMan(username) {
console.log(' Hi I am ' + username);
var temp = {
taskList: [],
sleepFirst(timeout) {
return () => {
setTimeout(() => {
console.log(`等待了${timeout}秒...`);
this.next();
}, timeout * 1000);
};
},
sleep(timeout) {
return () => {
setTimeout(() => {
console.log(`等待了${timeout}秒...`);
this.next();
}, timeout * 1000);
};
},
eat(type) {
return () => {
console.log(`I am eating ${type}`);
this.next();
};
},
next() {
var fn = this.taskList.shift();
fn && fn();
}
};
var proxy = new Proxy(temp, {
get(target, key, receiver) {
return function(...rest) {
if (key === 'sleepFirst') {
target.taskList.unshift(target[key](rest));
} else {
target.taskList.push(target[key](rest));
}
return receiver;
};
}
});
setTimeout(() => {
temp.next();
}, 0);
return proxy;
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
function LazyMan(name) {
console.log("Hi I am Tony");
return {
sleepTime: 0,
firstSleepTime: 0,
sleep: function(second) {
let time = 0;
function logText() {
setTimeout(() => {
console.log("等待了十秒...");
}, time);
}
setTimeout(() => {
time = second * 1000 + this.firstSleepTime * 1000;
logText();
}, 0);
this.sleepTime = this.sleepTime + second;
return this;
},
eat: function(meal) {
let time = this.sleepTime * 1000;
function logText() {
setTimeout(() => {
console.log("I am eating " + meal);
}, time);
}
setTimeout(() => {
time = time + this.firstSleepTime * 1000;
logText();
}, 0);
return this;
},
sleepFirst: function(second) {
let time = second * 1000;
setTimeout(() => {
console.log("等待了5秒");
}, time);
this.firstSleepTime = second;
return this;
}
};
};
写个链表实现
class Node {
constructor(func = null) {
this.func = func;
this.next = null;
}
async exec() {
if (this.func) {
await this.func();
}
if (this.next && this.next.func) {
this.next.exec();
}
}
}
function delayFunc(delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${delay}秒...`);
resolve();
}, delay * 1000);
});
}
class Lazy {
constructor(name) {
this.name = name;
this.head = new Node();
this.current = this.head;
Promise.resolve().then(() => this.head.exec());
}
eat(sth) {
const log = () => {
console.log("I am eating " + sth);
};
this.current.next = new Node(log);
this.current = this.current.next;
return this;
}
sleep(delay) {
this.current.next = new Node(() => delayFunc(delay));
this.current = this.current.next;
return this;
}
sleepFirst(delay) {
let head = new Node(() => delayFunc(delay));
if (!this.head.func) {
head.next = this.head.next;
} else {
head.next = this.head;
}
this.head = head;
return this;
}
}
function LazyMan(name) {
console.log("I am " + name);
return new Lazy(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
function LazyMan(name){
return new class LazyMan{
constructor(name){
this.tasks=[]
this.hello(name)
setTimeout(this.next.bind(this),0)
}
log(str){console.log(str);return true}
next(){
var fn=this.tasks.shift()
fn&&fn.apply(this)
}
hello(name){
this.tasks.push(()=>this.log('hello '+name)&&this.next())
return this
}
sleepfirst(time){
this.tasks.unshift(()=>this.log('sleep '+time)&&setTimeout(this.next.bind(this),time))
return this
}
eat(what){
this.tasks.push(()=>this.log('eat '+what)&&this.next())
return this
}
sleep(time){
this.tasks.push(()=>this.log('sleep '+time)&&setTimeout(this.next.bind(this),time))
return this
}
}(name)
}
/**
* 普通 eat方法, 存放在立即执行队列中, 用settimeout来执行
* sleep 方法 每次调用这个方法, 都单独开一个定时器, 把新的任务加入到这个队列
* sleepFirst方法 把立即执行的任务队列的任务 塞到新的定时器任务队列
*/
class LazymanClass {
constructor (_name = '') {
this._immediateTask = []
this._immediateTimer = null
this._sleepTaskMap = {}
this._curSleepTaskKey = null
this._log(`Hi i am ${_name}`)
}
eat (meal) {
// 添加新任务之前 清空之前的 立即定时器
this._immediateTimer && clearTimeout(this._immediateTimer)
const _eat = (meal) => {
this._log(`i am eating ${meal}`)
}
if (this._curSleepTaskKey === null) {
this._immediateTask.push(_eat.bind(this, meal))
} else {
this._sleepTaskMap[this._curSleepTaskKey].push(_eat.bind(this, meal))
}
this._immediateTimer = setTimeout(() => {
this._runImmeadiateTask()
})
return this
}
sleep (second) {
const key = Math.random()
this._curSleepTaskKey = key
this._sleepTaskMap[this._curSleepTaskKey] = []
setTimeout(() => {
this._log(`等待了${second}秒`);
this._runSleepTask(key)
}, second * 1000)
return this
}
sleepFirst (second) {
const key = Math.random()
this._curSleepTaskKey = key
this._sleepTaskMap[key] = []
this._immediateTask.map(task => {
this._sleepTaskMap[key].push(task)
})
this._immediateTask = []
setTimeout(() => {
this._log(`等待了${second}秒`);
this._runSleepTask(key)
}, second * 1000)
return this
}
_runImmeadiateTask () {
this._immediateTask.map(task => {
typeof task === 'function' && task()
})
this._immediateTask = []
}
_runSleepTask (key) {
this._sleepTaskMap[key].map(task => {
typeof task === 'function' && task()
})
this._sleepTaskMap[key] = []
}
_log(str) {
console.log(str)
}
}
function LazyMan(name) {
return new LazymanClass(name)
}
const test = () => {
// LazyMan('Tony')
// LazyMan('Tony').eat('lunch')
// LazyMan('Tony').sleep(2).eat('lunch')
// LazyMan('Tony').eat('lunch').sleep(2).eat('diner')
LazyMan('Tony').eat('lunch').eat('diner').sleepFirst(1).sleep(2).eat('junk food')
}
test()
class LazyManClass {
constructor(props){
this.sub = []
console.log(`Hi I am ${props}`)
setTimeout(()=>{
this.start()
},0)
}
eat (params){
this.sub.push(function(){
console.log(`I am eating ${params}`)
})
return this
}
sleepFirst(s){
this.sub.unshift(this.delay(s))
// 这边还没有返回 同步就继续执行了
return this
}
delay(s) {
return () => {
return new Promise(resolve => {
setTimeout(function () {
console.log(`等待了${s}秒...`)
resolve()
},s * 1000)
})
}
}
sleep (s){
this.sub.push(this.delay(s))
// 这边还没有返回 同步就继续执行了
return this
}
async start(){
for (const iterator of this.sub) {
await iterator()
}
}
}
function LazyMan(props) {
return new LazyManClass(props)
}
LazyMan('Tony').eat('lunch').eat('diner').sleepFirst(1).sleep(2).eat('junk food')
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
function LazyMan(name) {
if (!(this instanceof LazyMan)) {
return new LazyMan(name);
}
this.name = name;
this.delayTime = 0;
this.tasks = [];
console.log(`Hi I am ${this.name}`);
this._ready();
}
LazyMan.prototype._ready = function () {
setTimeout(() => {
setTimeout(() => {
console.log(`等待了${this.delayTime}秒...`);
this._doTasks();
}, this.delayTime * 1000);
}, 0);
}
LazyMan.prototype._doTasks = function () {
const tasks = this.tasks;
if (tasks.length === 0) return;
const {delayTime, callback} = tasks[0];
setTimeout(() => {
callback && callback();
tasks.shift();
this._doTasks();
}, delayTime);
}
LazyMan.prototype.eat = function (foods) {
this.tasks.push({
delayTime: 0,
callback() {
console.log(`I am eating ${foods}`);
},
});
return this;
}
LazyMan.prototype.sleep = function (seconds) {
if (seconds >= 0) {
this.tasks.push({
delayTime: seconds * 1000,
callback() {
console.log(`等待了${seconds}秒...`)
}
});
}
return this;
}
LazyMan.prototype.sleepFirst = function (seconds) {
if (seconds > 0) {
this.delayTime = seconds;
}
return this;
}
function LazyMan(name) {
if (this instanceof LazyMan) {
this.task = [];
this.log('Hi I am '+ name);
setTimeout(() => {
this.next();
}, 0);
}
return (this instanceof LazyMan) && this || new LazyMan(name);
}
LazyMan.prototype.log = console.log;
LazyMan.prototype.next = function() {
const [fn, ...tail] = this.task;
fn && (this.task = tail) && fn();
}
LazyMan.prototype.eat = function(food) {
this.task = [
...this.task,
() => {
this.log('I am eating '+ food);
this.next();
}
]
return this;
}
LazyMan.prototype.sleep = function(timeout) {
this.task = [
...this.task,
() => {
setTimeout(() => {
this.next();
}, timeout * 1000);
}
]
return this;
}
LazyMan.prototype.sleepFirst = function(timeout) {
this.task = [
() => {
setTimeout(() => {
this.next();
}, timeout * 1000)
},
...this.task
]
return this;
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(1).sleep(2).eat('junk food');
// 写一个 setTimeout 就可以了。
class lazyManClass {
constructor(name){
this.taskList = []
this.init(name)
}
init(name){
var _this = this
this.taskList.push({
time: 0, // 是否是异步
fn:(function(s){ // 函数自执行
return function() {
_this.exec()
console.log('Hi I am ', s)
}
})(name)
})
this.exec()
return this
}
eat(str) {
var _this = this
this.taskList.push({
time: 0,
fn: (function(s){
return function() {
_this.exec()
console.log('I am eating ', s)
}
})(str)
})
return this
}
sleep(t){
var _this = this
this.taskList.push({
time: t * 1000,
fn: (function(time){
return function() {
_this.exec()
console.log(`等待了${time}秒...`)
}
})(t)
})
return this
}
sleepFirst(t) {
var _this = this
this.taskList.unshift({
time: t * 1000,
fn: (function(time){
return function() {
_this.exec()
console.log(`等待了${time}秒...`)
}
})(t)
})
return this
}
exec(){
var obj = this.taskList.shift()
if(!obj) {
return // 最后一个fn里面,也会执行 _this.exec(),这个时候taskList已经空了
}
setTimeout(() => {
obj.fn && obj.fn.call(this)
}, obj.time || 0)
}
}
function LazyMan(name) {
return new lazyManClass(name)
}
class LazyMan {
constructor (user) {
this.timeList = [];
console.log(`Hi I am ${user}`)
Promise.resolve().then(res => this.next());
}
eat (res) {
var fn = () => {
console.log(`I am eating ${res}`);
this.next();
}
this.timeList.push(fn);
return this;
}
sleep (time) {
var fn = res => {
setTimeout(res => {
console.log(`等待了${time}秒`);
this.next();
},time*1000)
}
this.timeList.push(fn);
return this;
}
next () {
var fn = this.timeList.shift();
fn && fn();
}
sleepFrist (time) {
var fn = res => {
setTimeout(res => {
console.log(`先等待了${time}秒`);
this.next();
},time*1000)
}
this.timeList.unshift(fn);
return this;
}
}
function lazyman (res) {
return new LazyMan(res)
}
_//lazyman('静静').sleep(2).eat('饺子').sleep(3).eat('面').sleepFrist(1).eat('others')
//Hi I am 静静
//先等待了1秒
//等待了2秒
//I am eating 饺子
//等待了3秒
//I am eating 面
//I am eating others_
class LazyMan {
constructor(name) {
this.tasks = []
const task = () => {
console.log(name)
}
this.tasks.push(task)
setTimeout(() => {
this.exec()
})
}
sleep(time) {
const task = () => new Promise(resolve => {
setTimeout(resolve, time)
})
this.tasks.push(task)
return this
}
sleepFirst(time) {
const task = () => new Promise(resolve => {
setTimeout(resolve, time)
})
let originTask = this.tasks.shift()
this.tasks.unshift(originTask,task)
return this
}
eat(food) {
const task = () => {
console.log(food)
}
this.tasks.push(task)
return this
}
async exec() {
for (let task of this.tasks) {
await task()
}
}
}
function LazyManClass(name){
this.name = name;
console.log('Hi I am '+name);
//存储行为列表
this.taskList = [];
//声明类行为执行函数
this.doTask = function(){
var fn = this.taskList.shift();
if(fn){
fn();
}
};
//异步执行默认行为函数
var _this = this;
setTimeout(function(){
_this.doTask();
},0);
}
LazyManClass.prototype.eat = function(food){
var _this = this;
var fn = function(){
console.log('I am eating '+food);
_this.doTask();
}
//维护行为列表
this.taskList.push(fn);
return this;
}
LazyManClass.prototype.sleepFirst = function(time){
var _this = this;
var fn = function(){
setTimeout(function(){
console.log('等待了 '+time+'秒...');
_this.doTask();
},time*1000)
}
//维护行为列表
this.taskList.unshift(fn);
return this;
}
LazyManClass.prototype.sleep = function(time){
var _this = this;
var fn = function(){
setTimeout(function(){
console.log('等待了 '+time+'秒...');
_this.doTask();
},time*1000)
}
//维护行为列表
this.taskList.push(fn);
return this;
}
//函数调用返回实例化对象
function LazyMan(name){
return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
//感谢各位前辈们的代码思路,自己用es5写了一遍
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完
如果真是这样那就好理解了,谢谢解答!!
function LazyMan(name) {
console.log(`I am ${name}`);
var task = [];
function execute() {
var fn = task.shift();
fn && fn();
}
// delay execute
setTimeout(function() {
execute();
}, 0);
function _sleep(n = 0) {
console.log(`${name} is sleeping ${n}`);
setTimeout(function() {
execute();
}, n * 1000);
}
function _eat(food) {
console.log(`${name} is eating ${food}`);
execute();
}
var obj = {
sleep: function() {
task.push(_sleep.bind(null, ...arguments));
return obj;
},
eat: function() {
task.push(_eat.bind(null, ...arguments));
return obj;
},
sleepFirst: function() {
task.unshift(_sleep.bind(null, ...arguments));
return obj;
}
};
return obj;
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完
如果真是这样那就好理解了,谢谢解答!!
在constructor中, next()方法执行在 setTimeout 中,setTimeout 是一个task,当 js 运行到 setTimeout 的时候,会把他放到 task 任务队列中,等到所有的同步的任务执行完后,就会执行setTimeout 中的this.next()方法 , 这个问题的关键问题是 js 的事件队列问题 。 你可以参考这个链接详细了解 https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7?from=groupmessage&isappinstalled=0
@GuidingStarKe
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完
如果真是这样那就好理解了,谢谢解答!!
在constructor中, next()方法执行在 setTimeout 中,setTimeout 是一个task,当 js 运行到 setTimeout 的时候,会把他放到 task 任务队列中,等到所有的同步的任务执行完后,就会执行setTimeout 中的this.next()方法 , 这个问题的关键问题是 js 的_事件队列问题_ 。 你可以参考这个链接详细了解 https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7?from=groupmessage&isappinstalled=0
首先谢谢解答和分享!
class LazyMan {
constructor(name){
this.name = name
this.eventQueue = []
console.log('Hi , I am %s.', name )
setTimeout(()=>{
this.drain()
},0)
}
eat(meal){
const fn = function _eat(next){
console.log('I am eating %s.',meal)
next && next()
}
this.eventQueue.push(fn)
return this
}
sleep(second){
const fn = function _sleep(next){
console.log('I am waiting %d second.', second)
setTimeout(()=>{
next && next()
},second*1000)
}
this.eventQueue.push(fn)
return this
}
sleepFirst(second){
const fn = function _sleepFirst(next){
console.log('I am waiting %d second.', second)
setTimeout(()=>{
next && next()
},second*1000)
}
this.eventQueue.splice(0,0,fn)
return this
}
drain(){
const fnComposed = this.eventQueue.reduceRight(function _reduceRight(pre,next){
return function (){
return next(pre)
}
},)
fnComposed()
}
}
const TonyStark =new LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
用了async,不需callback, 下面是两种方法放一起了。 第一种方法注释掉了,调用任务eat或者sleep或者sleepFirst时,把任务的data存放队列里,在init的方法里异步调用async executeTasks, 任务存放是同步的,先于异步的方法executeTasks执行完,在executeTasks方法里依次让任务data出列,然后执行相应的任务。
第二种是,使用next方法,每个任务最后都会调用一次next方法,把每个任务都压入队列,next的一次调用也是异步的,晚于同步的任务入列执行,next方法里让当前的任务入列,并执行。
function LazyMan(name) {
return new LazyManClass(name);
}
class LazyManClass {
constructor(name) {
this.taskList = [];
// used for method executeTasks
// this.taskDataList = [];
this.init(name);
}
init(name) {
this.printLog('name', name);
setTimeout(() => {
// the alternative solution
//this.executeTasks();
this.next();
}, 0);
}
printLog(type, data) {
const LOG_MAP = {
'name': `Hi, I am ${data}`,
'eat': `I am eating ${data}.`,
'sleep': `Waited for ${data} seconds.`,
'error': `Got something wrrong: ${data}.`
};
console.log(LOG_MAP[type]);
}
delayPromise(t) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, t * 1000);
});
};
createTaskData(type, data) {
return { type, data };
}
createTask(type, data) {
return async () => {
if (type === 'sleep') {
try {
await this.delayPromise(data);
}
catch(e) {
this.printLog('error', e);
}
}
this.printLog(type, data);
this.next();
}
}
addTask(type, data, isFirst=false) {
if (isFirst) {
// used for method executeTasks
// this.taskList.unshift(this.createTask(type, data));
this.taskList.unshift(this.createTask(type, data));
} else {
// used for method executeTasks
// this.taskList.unshift(this.createTask(type, data));
this.taskList.push(this.createTask(type, data));
}
}
eat(str) {
this.addTask('eat', str);
return this;
}
sleep(t) {
this.addTask('sleep', t);
return this;
}
sleepFirst(t) {
this.addTask('sleep', t, true);
return this;
}
next() {
if (this.taskList.length > 0) {
let task = this.taskList.shift();
task && task();
}
}
async executeTasks() {
let taskDataList = this.taskDataList;
while (taskDataList.length > 0) {
let { type, data } = taskDataList.shift();
if (type === 'sleep') {
try {
await this.delayPromise(data);
}
catch(e) {
this.printLog('error', e);
}
}
this.printLog(type, data);
}
}
}
有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗
var fn = (n) => { console.log(n) }
你这样写,n的找不到name 你这样写,fn是个函数,而fn执行的时候是在next方法里执行的。而fn需要的的参数,你怎么获取到name呢?
在 2019-04-29 18:25:18,"kk" [email protected] 写道:
有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.
有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗
立即执行函数的作用是在内部函数还没有执行的时候就已经为内部函数绑定好了对应参数的值,如果不用立即函数的话也可以用bind方法
var name = '小明'
var fn = function (n){
console.log(`I am eating ${n}`)
this.next()
}.bind(null, name)
上面的代码实际上是让fn等于下面这个函数:
function (){
console.log(`I am eating 小明`)
this.next()
}
这样一来无论你在什么地方执行fn都不需要传参数了,直接fn()
不用参数也能达到和普通fn的fn(name )
效果一样了
不用类的实现,js里基本用类实现的用对象也可以实现。
LazyMan('Tony')
// Hi I am Tony
LazyMan('Tony')
.sleep(10)
.eat('lunch')
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
LazyMan('Tony')
.eat('lunch')
.sleep(10)
.eat('dinner')
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony')
.eat('lunch')
.eat('dinner')
.sleepFirst(5)
.sleep(10)
.eat('junk food')
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
下面是实现
let man = {
queue: []
}
function LazyMan(name) {
console.log(`Hi I am ${name}`)
setTimeout(() => {
man.next()
}, 0)
return man
}
man.eat = food => {
man.queue.push(() => {
console.log(`I am eating ${food}`)
man.next()
})
return man
}
man.sleep = timeout => {
man.queue.push(() => {
setTimeout(() => {
console.log(`等待了${timeout}秒`)
man.next()
}, timeout * 1000)
})
return man
}
man.sleepFirst = timeout => {
man.queue.unshift(() => {
setTimeout(() => {
console.log(`等待了${timeout}秒`)
man.next()
}, timeout * 1000)
})
return man
}
man.next = () => {
if (man.queue.length > 0) {
man.queue.shift()()
}
}
const LazyMan = name => new class Cp {
constructor(name) {
this.name = name;
this._queues = []
console.log(` Hi I am ${name}`)
Promise.resolve().then(() => {
this.next()
})
// return this
}
static _sleep = time => new Promise(resolve => setTimeout(resolve, time * 1000))
eat(ft) {
this._queues.push(() => {
console.log(`I am eating ${ft}`)
this.next()
})
return this
}
sleepFirst(time) {
this._queues.unshift(async () => {
await Cp._sleep(time)
console.log(`等待了 ${time} 秒`)
this.next()
})
return this
}
sleep(time) {
this._queues.push(async () => {
await Cp._sleep(time)
console.log(`等待了 ${time} 秒`)
this.next()
})
return this
}
next() {
const fn = this._queues.shift();
fn && fn()
}
}(name)
LazyMan('Tom');
LazyMan('Tom').sleep(10).eat('lunch')
LazyMan('Tom').eat('lunch').sleep(3).eat('dinner')
LazyMan('Tom').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
class LazyMan {
constructor(name) {
this.promise = Promise.resolve().then(() => console.log(`Hi I am ${name}`))
}
sleepFirst(time) {
this.promise = this.promise.then(() => new Promise(resolve => setTimeout(resolve, time * 1000)))
return this
}
eat(name) {
setTimeout(() => {
this.promise = this.promise.then(() => console.log(`I am eating ${name}`))
}, 0)
return this
}
sleep(time) {
setTimeout(() => {
this.promise = this.promise.then(() => new Promise(resolve => setTimeout(resolve, time * 1000)))
}, 0)
return this
}
}
不知道符不符合要求
class LazyManClass {
constructor (username) {
this.username = username
this.taskList = []
this._hello()
}
_addTask (task, data) {
clearTimeout(this.timer)
this.taskList.push(() => {
this[task](data)
})
this.timer = setTimeout(() => {
this._runTask()
})
return this
}
_runTask () {
for (let i = 0; i < this.taskList.length; i++) {
this.taskList[i]()
}
}
_insertTask (task, data, index) {
clearTimeout(this.timer)
this.taskList.splice(index, 0, () => {
this[task](data)
})
this.timer = setTimeout(() => {
this._runTask()
})
return this
}
registerBehave (name, action) {
this['_' + name] = action
this[name] = (data) => {
const fnName = '_' + name
if (/\w+First/.test(fnName)) {
this._insertTask(fnName, data, 0)
} else {
this._addTask(fnName, data)
}
return this
}
return this
}
_hello () {
console.log('Hi I am ' + this.username)
}
}
function LazyMan (name) {
const man = new LazyMan(name)
return man
.registerBehave('sleep', function (time) {
console.log('等待了 ' + time + ' 秒种...')
})
.registerBehave('eat', function (mealName) {
console.log('I am eating ' + mealName)
})
.registerBehave('sleepFirst', function (time) {
console.log('等待了 ' + time + ' 秒种...')
})
}
LazyMan('Pikachu').eat('lunch').sleep(10).sleepFirst(8)
有点长……
但是这样行为就是可以注册的了,以后想加个 gamingFirst
之类的都可以。
用Generator做~
function LazyMan(str = "") {
return new (class {
list = [];
task;
constructor(str) {
this.list.push(`Hi I am ${str}`);
this.task = this.log();
setTimeout(() => this.task.next());
}
sleepFirst = t => {
this.list.splice(1, 0, t);
return this;
};
sleep = t => {
this.list.push(t);
return this;
};
eat = str => {
this.list.push(`I am eating ${str}`);
return this;
};
log = function*() {
for (const val of this.list) {
yield (() => {
if (typeof val !== "number") console.log(val);
setTimeout(() => this.task.next(), (val >> 0) * 1000);
})();
}
};
})(str);
}
LazyMan("Tony")
.eat("lunch")
.eat("dinner")
.sleepFirst(5)
.sleep(10)
.eat("junk food");
class ArrayInherit extends Array {
constructor(options) {
super(options);
this.options=options;
}
push(item) {
super.push(item);
this.options.pushCb(item)
}
}
class LazyMan {
constructor(name) {
this.name = name;
this.sleepQueue = new ArrayInherit({pushCb: function(item) {
setTimeout(() => {
item.cb();
}, item.sleepWait)
}});
this.queueCb = [];
this.sleepWaitTemp = 0;
console.log(`Hi I am ${this.name}`);
}
sleep(sleepWait) {
this.sleepWaitTemp = sleepWait;
return this;
}
sleepFirst(sleepFirstWait) {
const queueCbTemp = this.queueCb;
this.queueCb = []
setTimeout(() => {
queueCbTemp.forEach(cb => {
cb();
})
}, sleepFirstWait)
return this;
}
get hasSleeped() {
return this.sleepWaitTemp > 0;
}
eat(thing) {
function cb() {
console.log(`I am eating ${thing}`);
}
if (this.hasSleeped) {
this.queueCb.forEach(cb => {
cb();
})
this.queueCb = []
this.sleepQueue.push({
sleepWait: this.sleepWaitTemp,
cb: cb.bind(this, thing)
});
} else {
this.queueCb.push(cb.bind(this, thing))
}
return this;
}
}
var a = new LazyMan('Tom');
a.sleep(1000).eat('lunch');
var a = new LazyMan('Tom');
a.eat('lunch').sleep(1000).eat('dinner');
var a = new LazyMan('Tom');
a.eat('lunch').eat('dinner').sleepFirst(2000).sleep(5000).eat('junk food')
其实题目主要考虑的点有以下几个方面:
- 链式调用 -> return this
- 链式调用终止判断 -> 我用了setTimeout会在被主线程pendding的方式,楼上的很多方案其实更好
- 依次执行一个异步数组 -> 同样楼上很多Promise的嵌套方案就很好,我是采用了递归,最后一次性执行
function LazyMan (name) {
console.log('Hi I am Tony')
return {
loops: [],
tick: null,
eat (something) {
this.wait()
this.loops.push(() => new Promise(resolve => {
resolve(true)
console.log('I am eating ' + something)
}))
return this
},
sleep (time) {
this.wait()
this.loops.push(() => new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
resolve(true)
}, time * 1000)
}))
return this
},
sleepFirst (time) {
this.wait()
this.loops.unshift(() => new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
resolve(true)
}, time * 1000)
}))
return this
},
wait () {
clearTimeout(this.tick)
this.tick = setTimeout(() => {
this.done()
})
},
done () { // 处理所有的操作
if (this.loops.length > 0) {
this.loops.shift()().then(() => {
this.done()
})
}
},
}
}
function LazyMan (name) {
let obj = Object.create(LazyMan.prototype);
obj.name = name;
obj.taskList = [];
console.log(Hi I am ${name}
);
obj.next();
return obj;
}
LazyMan.prototype.eat = function (message) { this.taskList.push({ type: 'eat', payload: message }); return this; };
LazyMan.prototype.sleep = function (time) { this.taskList.push({ type: 'sleep', payload: time }); return this; };
LazyMan.prototype.sleepFirst = function (time) { this.taskList.unshift({ type: 'sleep', payload: time }); return this; };
LazyMan.prototype.next = function () {
const self = this;
setTimeout(async function () {
let task = null;
while (task = self.taskList.shift()) {
switch (task.type) {
case 'sleep': {
await new Promise((resolve) => setTimeout(resolve, task.payload * 1000));
console.log(等待了${task.payload}秒
);
break;
}
case 'eat': {
console.log(I am eating ${task.payload}
);
break;
}
}
}
}, 0);
}
class LazyManClass {
constructor(name) {
this.taskList = []
this.name = name
console.log(`Hi I am ${name}`)
setTimeout(() => {
this.next()
}, 0)
}
eat (name) {
this.taskList.push(() => {
console.log(`I am eating ${name}`)
this.next()
})
return this
}
sleep (delay) {
this.taskList.push(() => {
setTimeout(() => {
console.log(`等待了${delay}秒...`)
this.next()
}, delay * 1000)
})
return this
}
sleepFirst (delay) {
this.taskList.unshift(() => {
setTimeout(() => {
console.log(`等待了${delay}秒...`)
this.next()
}, delay * 1000)
})
return this
}
next () {
const fn = this.taskList.shift()
fn && fn()
}
}
function LazyMan(name) {
return new LazyManClass(name)
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
执行Promise队列
class Lazy {
constructor(name) {
console.log(`Hi I am ${name}`);
this.task = [];
setTimeout(() => {
this.execQueue(0);
}, 0);
}
execQueue(index) {
var that = this;
if (that.task.length && index < that.task.length) {
that.task[index]().then(res => {
if (res) {
that.execQueue(++index);
}
})
}
}
sleep(s) {
this.task.push(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`等待了${s}秒...`)
resolve(true)
}, s * 1000);
})
})
return this;
}
sleepFirst(s) {
this.task.unshift(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`等待了${s}秒...`)
resolve(true)
}, s * 1000);
})
})
return this;
}
eat(str) {
this.task.push(() => {
return new Promise((resolve, reject) => {
console.log(`I am eating ${str}`);
resolve(true);
});
})
return this;
}
}
function LazyMan(name) {
return new Lazy(name);
}
// LazyMan('Tony').sleep(10).eat('lunch');
// LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
LazyMan('Tony'); // Hi I am Tony LazyMan('Tony').sleep(10).eat('lunch'); // Hi I am Tony // 等待了10秒... // I am eating lunch LazyMan('Tony').eat('lunch').sleep(10).eat('dinner'); // Hi I am Tony // I am eating lunch // 等待了10秒... // I am eating diner LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food'); // Hi I am Tony // 等待了5秒... // I am eating lunch // I am eating dinner // 等待了10秒... // I am eating junk food
Answer
class LazyManClass { constructor(name) { this.taskList = []; this.name = name; console.log(`Hi I am ${this.name}`); setTimeout(() => { this.next(); }, 0); } eat (name) { var that = this; var fn = (function (n) { return function () { console.log(`I am eating ${n}`) that.next(); } })(name); this.taskList.push(fn); return this; } sleepFirst (time) { var that = this; var fn = (function (t) { return function () { setTimeout(() => { console.log(`等待了${t}秒...`) that.next(); }, t * 1000); } })(time); this.taskList.unshift(fn); return this; } sleep (time) { var that = this var fn = (function (t) { return function () { setTimeout(() => { console.log(`等待了${t}秒...`) that.next(); }, t * 1000); } })(time); this.taskList.push(fn); return this; } next () { var fn = this.taskList.shift(); fn && fn(); } } function LazyMan(name) { return new LazyManClass(name); } LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food');
为什么要写自执行函数自执行函数,感觉有点多余
function lazyMan(name) {
console.log(`Hi I am ${name}`);
const obj = {
task: [],
next() {
// 完成一个任务之后继续完成下面的直到没有任务为止
const task = this.task.shift();
task && task();
},
sleep(second) {
this.task.push(() => {
console.log(`等待${second}秒...`)
setTimeout(() => {
this.next();
}, second * 1000);
})
return this;
},
eat(name) {
this.task.push(() => {
console.log(`I am eating ${name}`)
this.next();
})
return this;
},
sleepFirst(second) {
this.task.unshift(() => {
console.log(`等待${second}秒...`);
setTimeout(() => {
this.next();
}, second * 1000);
})
return this;
}
};
// 先等收集任务
setTimeout(() => {
// 收集好之后开始第一个任务
obj.next();
})
return obj;
}
lazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
class LazyMan {
constructor(name) {
this.tasks = [];
// 启动 tasks,利用 then的 异步原理拿到已经填充好的tasks
Promise.resolve().then(() => {
this.nextTick()
})
console.log(`hi i am ${name}`);
}
sleep(delay) {
this.tasks.push(() => {
setTimeout(() => {
this.nextTick();
}, delay * 1000);
});
return this;
}
sleepFirst(delay) {
// unshift 插队到最前面
this.tasks.unshift(() => {
setTimeout(() => {
this.nextTick();
}, delay * 1000);
});
return this;
}
eat(what) {
this.tasks.push(() => {
console.log(`eating ${what}`);
this.nextTick();
});
return this;
}
nextTick() {
this.tasks.length && this.tasks.shift()();
}
}
class LazyMan {
constructor(name) {
this.name = name;
console.log(`Hi, I am ${name}`)
this.taskQueue = []
setTimeout(() => {
this.start()
})
}
async start() {
for (let task of this.taskQueue) {
await task()
}
}
eat(dinner) {
this.taskQueue.push(() => {
console.log(`I am eating ${dinner}`)
})
return this;
}
wait(time) {
return () => new Promise(resolve => {
setTimeout(() => {
console.log(`waiting ${time} second`)
resolve()
}, time * 1000)
})
}
sleep(time) {
this.taskQueue.push(this.wait(time))
return this;
}
sleepFirst(time) {
this.taskQueue.unshift(this.wait(time))
return this
}
}
// new LazyMan('test1').sleep(2).eat('lunch')
// new LazyMan('test2').eat('lunch').sleep(5).eat('dinner')
new LazyMan('test3').eat('lunch').eat('dinner').sleepFirst(2).sleep(3).eat('junk food')
function LazyMan(str) {
if (this.constructor !== LazyMan) {
return new LazyMan(str)
}
this.willDoThing= []
this.firstDoing = []
this.firstSleep = false
this._init(str)
}
LazyMan.prototype.init = function(str) {
console.log(Hi I am ${str}
);
Promise.resolve().then( => {
this.startDoing()
})
return this
}
LazyMan.prototype.startDoing = async function() {
if (this.firstSleep) {
await this.firstDoing0
this.willDoThing.forEach( async (v) => {await v()} )
}else {
this.willDoThing.forEach( async (v) => {await v()} )
}
}
LazyMan.prototype.sleepFirst = function(time) { this.firstSleep = true this.firstDoing.push(async() => { await sleep(time) console.log('first sleep'+time); }) return this }
LazyMan.prototype.sleep = function(time) { this.willDoThing.push(async() => { await sleep(time) console.log('sleep'+time); }) return this }
function sleep(time) { return new Promise((a,b) => { setTimeout(()=> a() ,time) }) } LazyMan('zz').sleep(1000).sleepFirst(2000)
//备注其他功能就给willdoingThing添加fn就可以了,只是试验了一下两个sleep函数,多了一个判断
function LazyMan(name) {
console.log(`Hi I am ${name}`);
const logArr = [];
const executor = {
_status: 'stoped',
async _actor() {
while (logArr.length) {
const { wait, text } = logArr.shift();
if (wait) await new Promise(resolve => setTimeout(resolve, wait));
console.log(text);
}
this._status = 'stoped';
},
async dispatch() {
if (this._status === 'running') return;
this._status = 'running';
await new Promise(resolve => setTimeout(resolve, 0));
this._actor();
},
};
return {
eat(food) {
logArr.push({
wait: 0,
text: `I am eating ${food}`,
});
executor.dispatch();
return this;
},
sleepFirst(second) {
logArr.unshift({
wait: second * 1000,
text: `等待了 ${second} 秒...`,
});
executor.dispatch();
return this;
},
sleep(second) {
logArr.push({
wait: second * 1000,
text: `等待了 ${second} 秒...`,
});
executor.dispatch();
return this;
},
};
}
function LazyMan(name) {
var o = new Object();
o.name = name;
console.log(`Hi I am ${o.name}`);
o.message = [];
setTimeout(() => {
o.next();
}, 0);
o.eat = function (food) {
var fn = function () {
console.log(`I am eating ${food}`);
o.next();
}
o.message.push(fn);
return o;
}
o.sleepFirst = function (time) {
var fn = function () {
setTimeout(function () {
console.log(`等待了${time}秒...`);
o.next();
}, time * 1000);
}
o.message.unshift(fn);
return o;
}
o.sleep = function (time) {
var fn = function () {
setTimeout(function () {
console.log(`等待了${time}秒...`);
o.next();
}, time * 1000);
}
o.message.push(fn);
return o;
}
o.next = function () {
var fn = o.message.shift();
fn && fn();
}
return o;
}
LazyMan('Jack').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
class LazyManClass {
constructor (name) {
this.name = name
this.task = []
console.log('Hi I am ', name)
setTimeout(() => {
this.next()
}, 0)
}
eat (str) {
this.task.push(() => {
console.log('I am eating ', str)
this.next()
})
return this
}
sleep (n) {
this.task.push(() => {
setTimeout(() => {
console.log('等待了' + n + 's')
this.next()
}, n)
})
return this
}
sleepFirst (n) {
this.task.unshift(() => {
setTimeout(() => {
console.log('等待了' + n + 's')
this.next()
}, n)
})
return this
}
next () {
let fn = this.task.shift()
fn && fn()
}
};
let LazyMan = function (name) {
return new LazyManClass(name)
};
// LazyMan('Tony');
// Hi I am Tony
// LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
// LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
这道题的关键点有如下几个:
- 链式调用,通过返回 this 实现
- 内部需要维护一个 taskList ,根据不同逻辑,向 taskList 中push 、shift、unshift 执行函数
- 每执行一个task,需要继续执行后续 task,这通过 next 函数实现。
@zeroone001 请问为什么每个函数要通过闭包的形式,参考@lvwxx的形式,不需要闭包也能实现,请问使用闭包是出于什么考虑么
class MyClass{
constructor(name){
this.timer=null;
this.taskList=[];
console.log(`Hi I am ${name}`)
}
sleep(time){
this.run(async ()=>{
await new Promise(resolve=>setTimeout(resolve,time*1000))
console.log(`等待了${time}秒...`)
})
return this
}
sleepFirst(time){
this.run(async ()=>{
await new Promise(resolve=>setTimeout(resolve,time*1000))
console.log(`等待了${time}秒...`)
},'unshift')
return this
}
run(fun,act='push'){
if(this.timer)clearTimeout(this.timer);
this.taskList[act](fun)
this.timer=setTimeout(this.next.bind(this));
return this
}
async next(){
let current;
while(current=this.taskList.shift()){
await current()
}
}
eat(name){
this.run(()=>console.log(`I am eating ${name}`))
return this
}
}
function LazyMan(name){
return new MyClass(name)
}
const LazyManClass = class {
constructor(name) {
console.log('Hi I am ' + name)
this.isPendding = false
this.sleepCb = [[]]
this.sleeping = Promise.resolve()
}
get len() {
return this.sleepCb.length
}
sleepFirst(time) {
this.sleep(time)
return this
}
sleep(time) {
if (this.isPendding) {
this.sleepCb[this.len - 1].push(() => this.sleep(time))
} else {
this.sleepCb.push([])
const mySleepCb = this.sleepCb[this.len - 1]
this.sleeping = new Promise(resolve => {
this.isPendding = true
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.isPendding = false
resolve()
}, time * 1000)
})
this.sleeping.then(() => {
mySleepCb.forEach(fun => fun.call(this))
})
}
return this
}
eat(food) {
if (this.isPendding) {
this.sleepCb[this.len - 1].push(() => this.eat(food))
} else {
console.log('Hi I eating ' + food)
}
return this
}
}
const LazyMan = name => new LazyManClass(name)
class LazyManClass {
constructor(name){
this.name = name
this.queue = [] //队列
console.log(`Hi I am ${this.name}`)
setTimeout(() => {
this.nextTask()
}, 0);
}
sleep(time){
let task = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.nextTask()
}, time*1000);
}
this.queue.push(task)
return this
}
sleepFirst(time){
let task = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.nextTask()
}, time*1000);
}
this.queue.splice(0, 0, task)
return this
}
eat(food){
const task = () => {
console.log(`I am eating ${food}`)
this.nextTask()
}
this.queue.push(task)
return this
}
//下一任务
nextTask(){
let task = this.queue.shift()
task && task()
}
}
function LazyMan(name){
return new LazyManClass(name)
}
function LazyMan(name) {
if (this instanceof LazyMan) {
this.name = name;
this.taskQueue = [];
this.firstTaskQueue = [];
console.log('Hi I am Tony');
return this;
} else {
return new LazyMan(name);
}
}
LazyMan.prototype.eat = function(food) {
var func = function() {
console.log('I am eating ' + food);
};
var _this = this;
this.isSleeping ?
this.taskQueue.push(func)
: setTimeout(function() {
if (_this.isSleepFirst) {
_this.firstTaskQueue.push(func)
} else {
console.log('I am eating ' + food)
}
});
return this;
}
LazyMan.prototype.sleep = function(time) {
var _this = this;
this.isSleeping = true;
setTimeout(function() {
_this.isSleeping = false;
console.log('等待了' + time + '秒...');
const func = _this.taskQueue.shift();
func.call(_this);
}, time * 1000)
return this;
}
LazyMan.prototype.sleepFirst = function(time) {
var _this = this;
this.isSleepFirst = true;
setTimeout(function() {
_this.isSleepFirst = false;
console.log('等待了' + time + '秒...');
_this.firstTaskQueue.forEach(func => {
func.call(_this);
});
}, time * 1000)
return this;
}
const LazyManClass2 = class {
constructor(name) {
console.log('Hi I am ' + name)
this.tasks = []
setTimeout(() => this.next())
}
sleepFirst(time) {
this.tasks.unshift(() => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.next()
}, time * 1000)
})
return this
}
sleep(time) {
this.tasks.push(() => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.next()
}, time * 1000)
})
return this
}
eat(food) {
this.tasks.push(() => {
console.log('Hi I eating ' + food)
this.next()
})
return this
}
next(...args) {
const task = this.tasks.shift()
task && task.call(this, ...args)
}
}
const LazyMan = name => new LazyManClass2(name)
来一个使用 async await 解题的方案
const LazyManClass2 = class {
constructor(name) {
console.log('Hi I am ' + name)
this.tasks = []
setTimeout(() => this.run())
}
sleepFirst(time) {
this.tasks.unshift(async() => {
return new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
resolve()
}, time * 1000)
})
})
return this
}
sleep(time) {
this.tasks.push(async() => {
return new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
resolve()
}, time * 1000)
})
})
return this
}
eat(food) {
this.tasks.push(async() => {
console.log('Hi I eating ' + food)
})
return this
}
run() {
this.tasks.reduce(async(prev, curr) => {
await prev
return curr()
}, Promise.resolve())
}
}
const LazyMan = name => new LazyManClass2(name)
class LazyManClass {
constructor(name) {
this.queues = [];
console.log(`Hi I am ${name}!`);
setTimeout(() => {
this.next();
}, 0);
}
eat(food) {
this.queues.push(() => {
console.log(`I am eating ${food}`)
this.next();
});
return this;
}
sleep(seconds) {
this.queues.push(() => {
setTimeout(() => {
console.log(`等待了${seconds}秒`);
this.next();
}, seconds * 1000)
});
return this;
}
sleepFirst(seconds) {
this.queues.unshift(() => {
setTimeout(() => {
console.log(`等待了${seconds}秒`);
this.next();
}, seconds * 1000)
});
return this;
}
next() {
if (this.queues.length){
const fn = this.queues.shift();
fn && fn();
}
}
}
function LazyMan(name) {
return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food');
感觉立即执行函数有点多余,没必要加上
class LazyMats {
constructor(name){
this.name=name;
this.arr=[];
console.log(`Hi I am ${this.name}`)
setTimeout(() => this.next(), 0);
}
eat(lunch){
let fast=()=>{
console.log(lunch)
this.next()
}
this.arr.push(fast)
return this;
}
sleep(time){
let fast=()=>{
setTimeout(()=>{
console.log(`等待了${time}秒`)
this.next()
}, time*1000);
}
this.arr.push(fast)
return this;
}
sleepFirst(time){
let fast=()=>{
setTimeout(()=>{
console.log(`首先等待了${time}秒`)
this.next()
}, time*1000);
}
this.arr.unshift(fast);
return this;
}
next(){
let fn=this.arr.shift()
fn&&fn()
}
}
function LazyMan(name){
return new LazyMats(name)
}
LazyMan('Tony').eat('lunch').sleep(1).eat('dinner').sleepFirst(2).eat('junk food')
interface ILazyMan { name: string stack: Array<Function>
eat(food: string): any
sleep(wait: number): any
sleepFirst(wait: number): any
next()
}
// 这里面需要注意的是, 等待是异步操作, 我们先用同步将所有的事件都放到栈里面, 然后, 在通过next进行顺序执行, // 类似于 koa 里面的 next机制 class LazyMan implements ILazyMan { name: string; stack: Array<Function>;
constructor(name: string) {
this.name = name;
this.stack = [];
console.log(`我是${this.name}`);
// 这个 setTimeout 用来先让他们将同步完成, 完成之后, 在进行异步执行
setTimeout(() => {
this.next();
});
}
sleep(wait: number) {
this.stack.push(() => {
setTimeout(() => {
console.log(`我休息了${wait}s`);
this.next();
}, wait * 1000);
});
return this;
}
eat(food: string): any {
this.stack.push(() => {
console.log(`我正在吃${food}`);
this.next();
});
return this;
}
sleepFirst(wait: number): object {
this.stack.unshift(() => {
setTimeout(() => {
console.log(`我先休息了${wait}s`);
this.next();
}, wait * 1000);
});
return this;
}
next() {
const fn = this.stack.shift();
fn && fn();
}
}
let lazyNan = (name: string): ILazyMan => new LazyMan(name);
lazyNan('小芳').eat('firstFood').eat('lunch').sleepFirst(5).sleep(5).eat('dinner');
function LazyMan (name){
class Man{
constructor(name){
this.name = name
this.say()
this.eventList = [] //事件队列
this.dispatchEvent = false //事件调度,开启事件队列执行
}
say(){
console.log(`hi i am ${this.name}`)
return this
}
eat(name){
this.dispatchEvent = true
this.eventList.push((fn)=>{
console.log(`i am eating ${name}`)
fn.call(this,true)
})
Promise.resolve().then(()=>{ this.pollEvent() })
return this
}
sleep(time){
this.dispatchEvent = true
this.eventList.push((fn)=>{
const now = new Date() //sleep settimeout 来实现
setTimeout(()=>{
fn.call(this,true)
},time*1000)
})
Promise.resolve().then(()=>{ this.pollEvent() })
return this
}
sleepFirst(time){
this.dispatchEvent = true
this.eventList.unshift((fn)=>{
const now = new Date() // sleep 用超时来实现(个人推荐这里用settime来实现)
while( Date.parse( new Date() ) - Date.parse(now) < 1000 * time ){
continue
}
fn.call(this,true)
})
Promise.resolve().then(()=>{ this.pollEvent() })
return this
}
pollEvent(hasPoll){
//事件循环执行器
if(!this.dispatchEvent && !hasPoll ) return
this.dispatchEvent = false
let current = this.eventList.shift()
current && current.call(this,this.pollEvent)
}
}
return new Man(name)
}
function LazyMan (name) {
console.log(`Hi I am ${name}`);
let a = {
sleeping: false,
firstSleep: false,
init: true,
sleepArr: new Set([]),
firstSleepTime: 0,
sleep (time) {
if (!checkSleep(this.sleep.bind(this, time))) {
return this;
}
this.sleeping = true;
setTimeout(() => {
this.sleeping = false;
handleSleep();
}, time * 1000);
return this;
},
eat (val) {
if (!checkSleep(this.eat.bind(this, val))) {
return this;
}
console.log(`I am eating ${val}`);
return this;
},
sleepFirst (time) {
this.firstSleepTime += time * 1000;
return this;
}
}
function checkSleep(fn) {
if (a.sleeping || a.init) {
a.sleepArr.add(fn);
return false;
} else {
return true;
}
}
setTimeout(() => {
setTimeout(() => {
a.init = false;
handleSleep();
}, a.firstSleepTime);
}, 0);
function handleSleep () {
const sleepArr = a.sleepArr;
for (let item of sleepArr) {
item();
sleepArr.delete(item);
if (a.sleeping) {
break;
}
}
}
return a;
}
用promise实现了一下,只写了sleep、eat 方法,sleepFirst 类似sleep
function LazyMan(name) {
let progress = new Promise((resolve, reject) => {
console.log(`Hi I am ${name}`);
resolve();
})
return {
sleep: function (time) {
progress = progress.then(() => {
console.log(`等待了${time}毫秒`);
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), time)
})
})
return this
},
eat: function(text) {
progress = progress.then(() => {
return new Promise((resolve, reject) => {
console.log(`I am eating ${text}`);
resolve();
})
})
return this
}
}
}
class LazyManClass {
tasklist = []
constructor (name) {
console.log(`Hi I am ${name}`)
setTimeout(() => {
this.tasklist.reduce((preState, item) => {
return preState.then(item)
}, Promise.resolve())
}, 0)
}
eat (foods) {
this.tasklist.push(() => console.log(`I am eating ${foods}`))
return this
}
sleep (time) {
this.tasklist.push(() => {
return new Promise((res, rej) => {
setTimeout(() => {
res(console.log(`等待了${time}秒...`))
}, time * 1000)
})
})
return this
}
sleepFirst (time) {
this.tasklist.unshift(() => new Promise((res, rej) => {
setTimeout(() => {
res(console.log(`等待了${time}秒...`))
}, time * 1000)
}))
return this
}
}
const LazyMan = function (name) {
return new LazyManClass(name)
}
我用了很非常简单的方法实现的,不知道是否正确,请各位朋友指正。 思路如下: 1.给LazyMan设置是否休息的标志isSleep,sleep和sleepFirst方法都能将isSleep设置为真,并设置休息的时间sleepTime, eat方法根据isSleep决定是否延时执行 2.sleepFirst有优先执行权,sleepFirst中不设置setTimeout 3.要实现链式调用,所以每个方法都要返回this
class LazyManObject{
constructor(str) {
console.log('I am ' + str);
this.isSleep = false;
this.sleepTime = 0;
}
eat(str) {
setTimeout(() => {
if (!this.isSleep) {
console.log('I am eating ' + str);
} else {
setTimeout(() => {
console.log('I am eating ' + str);
this.sleepTime = 0;
this.isSleep = false;
return this;
}, this.sleepTime);
}
})
return this;
}
sleepFirst(num) {
this.sleepTime = num * 1000;
this.isSleep = true;
return this;
}
sleep(num) {
setTimeout(() => {
this.sleepTime = num * 1000;
this.isSleep = true;
})
return this;
}
}
function LazyMan(str) {
return new LazyManObject(str);
}
LazyMan('Jack').eat('breakfast').sleep(10).eat('lunch').sleepFirst(5);
class LazyManClass {
constructor(name) {
this._taskList = [];
console.info(`Hi I am ${name}`);
}
eat(foodName) {
this._addTask(() => {
console.info(`I am eat ${foodName}`);
return Promise.resolve();
});
return this;
}
sleep(seconds, first = false) {
let callback = () => new Promise((resolve) => {
setTimeout(() => {
resolve();
console.info(`等待了${seconds}秒钟...`);
}, seconds * 1000)
});
this._addTask(callback, first);
return this;
}
sleepFirst(seconds) {
return this.sleep(seconds, true);
}
_addTask(callback, first = false) {
let task = () => callback.call(this).finally(this._execute.bind(this));
if (first) {
this._taskList.unshift(task);
} else {
this._taskList.push(task);
}
this._execute();
}
_execute() {
if (this._taskList.length) {
clearTimeout(this._timeout);
this._timeout = setTimeout(() => {
if (this._taskList.length) {
let task = this._taskList.shift();
task();
}
}, 0);
}
}
}
function LazyMan(name) {
return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
感觉那些 next 的都是正统猿啊,学习了😂
function outSleep(t) {
return new Promise(r => {
setTimeout(() => {
console.log("");
console.log(`...outSleep ${t}`);
r();
}, 1000 * t);
});
}
function LazyMan(name) {
const lazy = {
_cbs: [],
_timer: null,
_init() {
if (name) console.log(`Hi I am ${name}`);
return this;
},
async _run() {
console.log("");
console.log(`===start`);
console.log(this._cbs);
console.log("");
for (let i = 0; i < this._cbs.length; i++) {
const fn = this._cbs[i];
await fn();
}
return this;
},
eat(food) {
this._cbs.push(function eat() {
console.log(`I am eating ${food}`);
});
clearTimeout(this._timer);
this._timer = setTimeout(() => {
this._run();
}, 0);
return this;
},
sleep(t) {
this._cbs.push(async function sleep() {
await outSleep(t);
});
return this;
},
sleepFirst(t) {
this._cbs.unshift(async function sleepFirst() {
await outSleep(t);
});
return this;
}
};
return lazy._init();
}
Hi I am Tony
===start
[ [AsyncFunction: sleepFirst],
[Function: eat],
[Function: eat],
[AsyncFunction: sleep],
[Function: eat] ]
...outSleep 5
I am eating lunch
I am eating dinner
...outSleep 1
I am eating junk food
简单点
function LazyMan(name) {
console.log('Hi I am ' + name)
const addTask = function (task, pos = 'last') {
if (!this.start) {
this.start = true
this.startTask()
}
if (pos === 'last') {
this.task.push(task)
} else {
this.task.unshift(task)
}
}
const startTask = function () {
setTimeout(async () => {
const task = [...this.task]
this.task = []
for (let i = 0; i < task.length; i++) {
let res = await task[i]()
}
this.start = false
})
}
const task = []
const sleep = function (time, pos = 'last') {
const taskFuc = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('等待了', time)
resolve('sad')
}, time * 1000)
})
}
this.addTask(taskFuc, pos)
return this
}
const eat = function (food) {
this.addTask(() => console.log('i am eat', food))
return this
}
const sleepFirst = function (time) {
this.sleep(time, 'first')
return this
}
return {
task,
sleep,
eat,
startTask,
start: false,
addTask,
sleepFirst,
}
}
为什么需要立即执行函数?
var fn = (function (t) {
return function () {
setTimeout(() => {
console.log(`等待了${t}秒...`)
that.next();
}, t * 1000);
}
})(time);
直接如下不行吗?
var fn = function () {
setTimeout(() => {
console.log(`等待了${t}秒...`)
that.next();
}, t * 1000);
};
class LazyManClass {
constructor(name) {
this.name = name;
this.callback = [];
this.firstStack = [];
this.stack = [];
console.log(`Hi I am ${this.name}`);
setTimeout(this.next.bind(this), 0);
}
eat(food) {
this.stack.push(() => {
return new Promise((resolve, reject) => {
console.log(`I am eating ${food}`);
resolve();
});
});
return this;
}
sleep(seconds) {
this.stack.push(() => {
return new Promise((resolve, reject) => {
console.log(`等待了${seconds}秒`);
setTimeout(resolve, seconds * 1000);
});
});
return this;
}
sleepFirst(seconds) {
this.firstStack.push(() => {
return new Promise((resolve, reject) => {
console.log(`等待了${seconds}秒`);
setTimeout(resolve, seconds * 1000);
});
});
return this;
}
next() {
if (this.firstStack.length > 0) {
this.firstStack.shift()().then(this.next.bind(this));
} else if (this.stack.length > 0) {
this.stack.shift()().then(this.next.bind(this));
}
}
}
function LazyMan(name) {
return new LazyManClass(name);
}
以上大部分是以事件队列的算法实现,我这里提供发布订阅的一种算法,供大家参考:
class Event {
maps = {};
fire(type) {
const stack = this.maps[type] || [];
stack.every(listener => listener());
}
listen(type, listener) {
if (!this.maps.hasOwnProperty(type)) {
this.maps[type] = [];
}
this.maps[type].push(listener);
}
remove(type, listener) {
const index = this.maps.indexOf(listener);
this.maps.splice(index, 1);
}
}
let EventItem = new Event();
let init = false;
function LazyMan(name){
this.sleepState = false;
if(!init){
console.log('Hi I am ' + name);
init = true;
return new LazyMan(name);
}
}
LazyMan.prototype.sleep = function(time){
function s(){
this.sleepState = true;
setTimeout(() => {
console.log('等待了' + time + '秒...');
this.sleepState = false;
EventItem.fire('sleepOver')
}, time * 1000);
}
if(!this.sleepState){
s()
}else{
EventItem.listen('sleepFirstOver', () => {
s()
});
}
return this;
}
LazyMan.prototype.sleepFirst = function(time){
this.sleepState = true;
setTimeout(() => {
console.log('等待了' + time + '秒...');
this.sleepState = false;
EventItem.fire('sleepFirstOver')
}, time * 1000);
return this;
}
LazyMan.prototype.eat = function(type){
if(!this.sleepState){
console.log('I am eating ' + type)
}else{
EventItem.listen('sleepOver', () => {
console.log('I am eating ' + type)
});
}
return this;
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
或许 next 的逻辑不应该放在队列里,队列应该做的只是保证根据优先级和先入先出来决定谁先出
class LazyMan {
constructor(name) {
this.name = name;
this.queue = [];
console.log(`Hi I am ${name}`);
setTimeout(this.apply.bind(this));
}
eat(something) {
this.queue.push(() => console.log(`I am eating ${something}`));
return this;
}
sleep(time) {
this.queue.push(async () => {
console.log(`等待了${time}秒...`);
return new Promise(res => setTimeout(res, time * 1000))
})
return this;
}
sleepFirst(time) {
this.queue.unshift(async () => {
console.log(`等待了${time}秒...`);
return new Promise(res => setTimeout(res, time * 1000))
})
return this;
}
async apply() {
const queue = this.queue;
while (queue.length) {
const todo = queue.shift();
await todo();
}
}
}
class LazyMan{
constructor (name) {
this.name = name
this.sleep = 0
this.sleepFirst = 0
console.log(`Hi I am ${this.name}`)
}
eat (what) {
setTimeout(()=>{setTimeout(()=>{console.log(`I am eating ${what}`)}, this.sleepFirst)}, this.sleep)
return this
}
Sleep (time) {
this.sleep = time
return this
}
SleepFirst (time) {
this.sleepFirst = time
return this
}
}
new LazyMan('Tony').eat('lunch').eat('dinner').Sleep(1000).eat('dinnerend').SleepFirst(2000)
有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗
立即执行函数的作用是在内部函数还没有执行的时候就已经为内部函数绑定好了对应参数的值,如果不用立即函数的话也可以用bind方法
var name = '小明' var fn = function (n){ console.log(`I am eating ${n}`) this.next() }.bind(null, name) 上面的代码实际上是让fn等于下面这个函数: function (){ console.log(`I am eating 小明`) this.next() }
这样一来无论你在什么地方执行fn都不需要传参数了,直接
fn()
不用参数也能达到和普通fn的fn(name )
效果一样了
为什么不直接
var fn = function () {
console.log(`I am eating ${name}`)
that.next();
}
// Lazyman
// 关键在于队列,taskQueue ,其实不是异步
function _Lazyman(name) {
return new Lazyman(name)
}
function Lazyman(name) {
this.name = name
this.taskQueue = []
// 但是启动的必须是异步,先都加入到队列,然后异步按照顺序执行
const asyncFunc = ()=>{
setTimeout(()=>{
console.log('I m '+ name)
this.runNext()
}, 0)
}
this.taskQueue.push(asyncFunc)
this.runNext() // 启动整个流程
}
Lazyman.prototype.eat = function(food) {
this.taskQueue.push(
// ()=>{
// setTimeout(()=>{
// console.log('eating ' + food)
// this.runNext()
// }, 0)
// }
()=>{
console.log('eating ' + food)
this.runNext()
}
)
return this
}
Lazyman.prototype.sleep = function(time) {
this.taskQueue.push( ()=> {
setTimeout(()=> {
this.runNext()
}, time)
} )
return this
}
Lazyman.prototype.runNext = function() {
let fn = this.taskQueue.shift() // 取第一个
fn && fn()
}
_Lazyman('kevin').eat('a').eat('b').sleep(3000).eat('c')
上面有的同学的思路很棒,就是不在队列的函数里面执行runNext,单独维护一个函数run整个queue里面的函数。
function LazyMan(name) {
console.log(`Hi I am ${name}`);
let tasks = [];
let run = () => {
if (tasks.length) {
let task = tasks.shift();
task && task();
}
};
setTimeout(() => {
run();
}, 0);
return {
sleep(time) {
tasks.push(() => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
run();
}, 1000 * time);
});
return this;
},
sleepFirst(time) {
tasks.unshift(() => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
run();
}, 1000 * time);
});
return this;
},
eat(what) {
tasks.push(() => {
console.log(`I am eating ${what}`);
run();
});
return this;
}
}
}
// test
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
网上看到一个比较好的思路 [(https://www.jianshu.com/p/f1b7cb456d37)] 分析了考察的要点 “ 1.方法链式调用 2.类的使用和面向对象编程的思路 3.设计模式的应用 4.代码的解耦 5.最少知识原则,也即 迪米特法则(Law of Demeter) 6.代码的书写结构和命名 ”
var _now = function() {return new Date()}
function LazyMan(name) {
console.log(`Hi I am ${name}`)
setTimeout(() => {}, 0);
return this
}
LazyMan.prototype.eat = function (type) {
setTimeout(() => {
console.log(`I am eating ${type}`)
}, 0);
return this
};
LazyMan.prototype.sleep = function (sec) {
var now = new Date();
setTimeout(() => {
while (_now() - now < sec * 1000) {}
console.log(`等待了${sec}秒`);
}, 0);
return this
};
LazyMan.prototype.sleepFirst = function (sec) {
var now = new Date();
while (_now() - now < sec * 1000) {}
console.log(`等待了${sec}秒`);
return this
};
class LazyManClass {
constructor(name) {
this.timeoutNum = 0
this.timeoutArr = []
this.index = 0
console.log(`Hi I am ${name}`)
setTimeout(() => {
this.go()
}, 0);
}
eat(type) {
this.timeoutArr.push({
timeout: this.timeoutNum,
type
})
this.timeoutNum = 0
return this
}
sleep(timeout) {
this.timeoutNum += (timeout *= 1000)
return this
}
sleepFirst(timeout) {
this.timeoutArr = this.timeoutArr.map(item => {
item.delay = true
item.timeout = timeout * 1000
return item
})
return this
}
go() {
let curTimeoutItem = this.timeoutArr[this.index++]
if (!curTimeoutItem) return false
setTimeout(() => {
do
console.log(`I am eating ${curTimeoutItem.type}`)
while ((curTimeoutItem = this.timeoutArr[this.index++]) && curTimeoutItem.delay);
if (this.timeoutArr[--this.index]) this.go()
}, curTimeoutItem.timeout);
}
}
const LazyMan = name => {
return new LazyManClass(name)
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
这个跟event-loop(事件循环)有关,感兴趣的可以来了解一下我这篇文章:https://chen-cong.blog.csdn.net/article/details/97107219
LazyMan('Tony');
// Hi I am Tony
LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
class LazyManClass {
constructor(name) {
this.name = name
this.queue = []
console.log(Hi I am ${name}
)
setTimeout(() => {
this.next()
},0)
}
sleepFirst(time) {
const fn = () => {
setTimeout(() => {
console.log(等待了${time}秒...
)
this.next()
}, time * 1000)
}
this.queue.unshift(fn)
return this
}
sleep(time) {
const fn = () => {
setTimeout(() => {
console.log(等待了${time}秒...
)
this.next()
},time * 1000)
}
this.queue.push(fn)
return this
}
eat(food) {
const fn = () => {
console.log(I am eating ${food}
)
this.next()
}
this.queue.push(fn)
return this
}
next() { const fn = this.queue.shift() fn && fn() } }
function LazyMan(name) { return new LazyManClass(name) } LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food');
你好,你的setTimeout里面没有乘1000,是毫秒,所以很快就输出了结果
在 2020年1月3日,下午2:42,GelaKola [email protected] 写道:
class LazyManClass { constructor(name) { this.name = name this.queue = [] console.log(
Hi I am ${name}
) setTimeout(() => { this.next() },0) }sleepFirst(time) { const fn = () => { setTimeout(() => { console.log(
等待了${time}秒...
) this.next() }, time) } this.queue.unshift(fn) return this }sleep(time) { const fn = () => { setTimeout(() => { console.log(
等待了${time}秒...
) this.next() },time) } this.queue.push(fn) return this }eat(food) { const fn = () => { console.log(
I am eating ${food}
) this.next() } this.queue.push(fn) return this }next() { const fn = this.queue.shift() fn && fn() } }
function LazyMan(name) { return new LazyManClass(name) } 你好你的这种写法如下调用,成功的输出了如下的输出,但是确没有真正等待5秒,4秒,而是一下子全部输出来的。
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food'); // Hi I am Tony // 等待了5秒... // I am eating lunch // I am eating dinner // 等待了4秒... // I am eating junk food — You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/98?email_source=notifications&email_token=AGIDOG2TGU5EMXIFR6COSLLQ33M3TA5CNFSM4HGPR7PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIANLZY#issuecomment-570480103, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGIDOG7NTMOVO2AA7X3VCNLQ33M3TANCNFSM4HGPR7PA.
function LazyMan(name) {
return new function () {
this.name = name
console.log(`Hi I am ${this.name}`)
this.events = []
this.firstEvents = []
this.eat = function (el) {
this.events.push(() => console.log(`I am eating ${el}`))
return this
}
this.sleepFirst = function(time){
this.firstEvents = this.events.map((event)=>event)
this.events = []
setTimeout(()=>{
time != 0 ? console.log(`等待了${time}秒...`) : null
this.firstEvents.forEach(event => event())
},time * 1000)
return this
}
this.sleep = function (time) {
if(this.firstEvents==0) this.events = this.events.filter(event => event())
setTimeout(()=>{
console.log(`等待了${time}秒...`)
this.events.forEach(event => event())
},time * 1000)
return this
}
}
}
LazyMan('Tony')
// Hi I am Tony
LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating dinner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
function LazyManClass(name) {
this.name = name;
console.log(`Hi I am ${this.name}`);
this.msgList = [];
Promise.resolve().then(async () => {
for(let i = 0; i < this.msgList.length; i ++) {
if (this.msgList[i].time > 0) {
await _sleep(this.msgList[i].time);
}
console.log(this.msgList[i].msg);
}
})
async function _sleep(t) {
await new Promise(resolve => setTimeout(() => resolve(), t*1000));
}
return this;
}
LazyManClass.prototype.eat = function(v) {
this.msgList.push({
time: 0,
msg: `I am eating ${v}`,
});
return this;
};
LazyManClass.prototype.sleep = function(t) {
this.msgList.push({
time: t,
msg: `等待了 ${t}秒...`,
});
return this;
};
LazyManClass.prototype.sleepFirst = function(t) {
this.msgList.unshift({
time: t,
msg: `等待了 ${t}秒...`,
});
return this;
};
function LazyMan(name) {
return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
class LazyManClass {
constructor(name) {
this.taskQueue = []
console.log(Hi I am ${name}
)
setTimeout(() => {
this.next()
})
}
sleep(second) {
let task = () => {
setTimeout(() => {
console.log(等待了${second}秒...
)
this.next()
}, second * 1000)
}
this.taskQueue.push(task)
return this
}
sleepFirst(second) {
let task = () => {
setTimeout(() => {
console.log(等待了${second}秒...
)
this.next()
}, second * 1000)
}
this.taskQueue.unshift(task)
return this
}
eat(food) {
let task = () => {
console.log('I am eating', food)
this.next()
}
this.taskQueue.push(task)
return this
}
next() {
let fn = this.taskQueue.shift()
fn && fn()
}
}
function LazyMan(name) {
return new LazyManClass(name)
}
class LazyMan {
constructor(name){
this.normalQueue = [];
this.sleepFistQueue = [];
this.name = name;
this.start();
return this;
}
start(){
this.delay(0, async ()=>{
let normalQueue = this.normalQueue;
let sleepFistQueue = this.sleepFistQueue;
// say hi
console.log(`Hi I am ${this.name}`);
// sleepFirstQueue
while(sleepFistQueue.length){
await sleepFistQueue.shift()();
}
// normalQueue
while(normalQueue.length){
await normalQueue.shift()();
}
})
}
delay(time = 0, fn){
return new Promise((resolve, reject) => {
window.setTimeout(()=>{
fn && fn();
resolve();
}, time*1000);
})
}
eat(food){
this.normalQueue.push(() => {
return this.delay(0, () => { console.log(`I am eating ${food}`)});
});
return this;
}
sleep(time){
this.normalQueue.push(() =>{
return this.delay(time, () => { console.log(`Delay ${time}s`)});
});
return this;
}
sleepFirst(time){
this.sleepFistQueue.push(() =>{
return this.delay(time, () => { console.log(`First delay ${time}s`)});
});
return this;
}
}
// test case
new LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
妈蛋,看了一遍大家的回答,发现我的写法最老派,果然是岁月不饶人...
function LazyMan(name) {
// 防止不通过new来调用
if (!(this instanceof LazyMan)) {
return new LazyMan(name);
}
this.name = name;
this.queue = [];
console.log(`I'm ${this.name}`);
return this.process();
}
LazyMan.prototype = {
process() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
let p = Promise.resolve();
while (this.queue.length) {
p = p.then(this.queue.shift());
}
}, 0);
return this;
},
eat(name) {
this.queue.push(() => {
return new Promise(resolve => {
console.log(name);
resolve();
});
});
return this.process();
},
sleep(sec) {
this.queue.push(() => {
return new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${sec}秒...`);
resolve();
}, sec * 10); // 方便测试 应该为1000
});
});
return this.process();
},
sleepFirst(sec) {
this.queue.unshift(() => {
return new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${sec}秒...`);
resolve();
}, sec * 10); // 方便测试 应该为1000
});
});
return this.process();
}
};
// 测试
var instance = LazyMan("Tony")
.eat("lunch")
.eat("dinner")
.sleepFirst(5)
.sleep(10)
.eat("junk food");
setTimeout(() => {
console.log("----again----");
instance
.eat("lunch")
.eat("dinner")
.sleepFirst(5)
.sleep(10)
.eat("junk food");
}, 1000);
function LazyMan (name) {
return new LazyManReduxStyle(name);
}
class LazyManReduxStyle {
constructor(name) {
this.name = name;
this.middlewares = [this._say()];
this.sleepFirstMiddlewares = [];
setTimeout(() => {
this._run();
});
}
sleepFirst(time) {
time = time * 1000;
this.sleepFirstMiddlewares.push(next => () => {
setTimeout(() => {
console.log(`Wake up after ${time} ms`);
next && next();
}, time);
});
return this;
}
sleep(time) {
time = time * 1000;
this.middlewares.push(next => () => {
setTimeout(() => {
console.log(`Wake up after ${time} ms`);
next && next();
}, time);
});
return this;
}
eat(food) {
this.middlewares.push(next => () => {
console.log(`Eat ${food}~`);
next && next();
});
return this;
}
_say() {
return next => () => {
console.log(`Hi, this is ${this.name}`);
next && next();
};
}
_run() {
this._applyMiddlewares([...this.sleepFirstMiddlewares, ...this.middlewares])();
}
_applyMiddlewares(middlewares) {
const [lastActionGenerator, ...restActionGenerators] = middlewares.reverse();
return compose(restActionGenerators)(lastActionGenerator());
}
}
function compose(funcs) {
return arg => funcs.reduce((acc, curr) => curr(acc), arg);
}
LazyMan('Hank').sleepFirst(3).eat('lunch').sleep(3).eat('dinner').sleepFirst(2);
最近看了下 Redux 中间件的原理,借鉴下他的思想写个 Lazyman 通过将下一个动作包裹成 next 放在前一个动作里面然后在适当的时机去调用 next,来实现流程的运行.
PS:这里的 sleepFirstMiddlewares 数组可以去掉,但是以前看到这题的时候他的要求是 sleepFirst 最先执行,但执行顺序与调用顺序相同,如果用 unshift 的话,无法实现执行顺序与调用顺序相同,所以就加了个新的数组,否则只用一个数组就够了
提升个难度: LazyMan('Tony').sleepFirst(5) // 等待了5秒 // Hi i am Tony
function LazyMan(name) {
console.log(`Hi I am ${name}`)
let totalSleepFirst = 0
let callbacks = []
function fire() {
if (totalSleepFirst) return
if (callbacks.length === 0) return
function run(){
if(callbacks.length === 0) return
callbacks.shift()().then(run)
}
run()
}
function eat(food) {
new Promise(resolve => {
setTimeout(() => {
resolve()
callbacks.push(() => Promise.resolve(console.log(`I am eating ${food}`)))
fire()
}, 0)
})
return man
}
function sleepFirst(delay) {
setTimeout(() => {
console.log(`等待了${delay}秒`)
totalSleepFirst -= delay
fire()
}, (delay + totalSleepFirst) * 1000)
totalSleepFirst += delay
return man
}
function sleep(delay) {
new Promise(resolve => {
setTimeout(() => {
resolve()
callbacks.push(() => new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${delay}秒`)
resolve()
}, delay * 1000)
}))
fire()
}, 0)
})
return man
}
const man = {
eat,
sleepFirst,
sleep
}
return man
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleepFirst(3).sleep(10).eat('junk food');
class LazyMan {
task = []
timer = null
constructor() {
return this.sayHi
}
sayHi = (name) => {
console.log(`Hi I am ${name}`)
return this
}
eat(food) {
this.task.push({ type: 'eat', value: food })
this.doIt()
return this
}
sleep(time) {
this.task.push({ type: 'sleep', value: time })
this.doIt()
return this
}
sleepFirst(time) {
this.task.unshift({ type: 'sleep', value: time })
this.doIt()
return this
}
_sleep (time) {
return new Promise(r => { setTimeout(() => { r() }, time * 1000) })
}
doIt () {
if (this.timer) clearTimeout(this.timer)
this.timer = setTimeout(async () => {
for (let i = 0; i < this.task.length; i++) {
const item = this.task[i]
if (item.type === 'eat') {
console.log(`I am eating ${item.value}`)
} else {
await this._sleep(item.value)
}
}
}, 0)
}
}
const lazyMan = new LazyMan()
lazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
function LazyMan(name) { console.log(`I am ${name}`); var task = []; function execute() { var fn = task.shift(); fn && fn(); } // delay execute setTimeout(function() { execute(); }, 0); function _sleep(n = 0) { console.log(`${name} is sleeping ${n}`); setTimeout(function() { execute(); }, n * 1000); } function _eat(food) { console.log(`${name} is eating ${food}`); execute(); } var obj = { sleep: function() { task.push(_sleep.bind(null, ...arguments)); return obj; }, eat: function() { task.push(_eat.bind(null, ...arguments)); return obj; }, sleepFirst: function() { task.unshift(_sleep.bind(null, ...arguments)); return obj; } }; return obj; } LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
大哥 人家说的是构建个类 不是 方法
全是大佬 看不懂
class LazyManClass {
constructor(name) {
this.name = name;
this.taskList = [];
this.init();
}
init() {
console.log(`Hi I am ${this.name}`);
setTimeout(() => {
this.next();
}, 0);
}
next() {
const task = this.taskList.shift();
task && task();
}
sleepFirst(interval) {
const task = () => {
setTimeout(() => {
console.log(`等待了${interval}秒...`);
this.next();
}, interval * 1000);
};
this.taskList.unshift(task);
return this;
}
sleep(interval) {
const task = () => {
setTimeout(() => {
console.log(`等待了${interval}秒...`);
this.next();
}, interval * 1000);
};
this.taskList.push(task);
return this;
}
eat(food) {
const task = () => {
console.log(`I am eating ${food}`);
this.next();
};
this.taskList.push(task);
return this;
}
}
const LazyMan = (name) => new LazyManClass(name);
LazyMan('Tony').eat('apple').sleepFirst(5).sleep(3).eat('mongo');
(1)实例化对象的时候,会向setTimeout宏任务队列添加一个任务,此时script宏任务还未执完,所以不会立即执行setTimeout中的this.next()。
(2)然后执行script宏任务中的eat(),它添加了eatAppleTask到taskList的最后。
taskList = [eatAppleTask]。
(3)执行script宏任务中的sleepFirst(), 它添加了sleepFirstTask到taskList的最前面。
taskList = [sleepFirstTask,eatAppleTask]。
(4)执行script宏任务中的sleep(), 它添加了sleepTask到taskList的最后。
taskList = [sleepFirstTask,eatAppleTask,sleepTask]。
(5)执行script宏任务中的eat(),它添加了eatMongoTask到taskList的最后。
taskList = [sleepFirstTask,eatAppleTask,sleepTask,eatMongoTask]。
(6)此时script宏任务执行完毕,执行栈被清空。于是读取下一个宏任务,也就是第一步中的setTimeout,发现这个任务是可执行的(计时时间为0,早就过了)。将其回调函数提取到执行栈中执行。
(7) 于是执行回调函数this.next()。taskList中的第一个task,也就是sleepFirstTask被执行。它向setTimeout宏任务队列添加一个任务。此时执行栈中没有程序要执行,于是读取setTimeout宏任务,但是异步处理还未完成(需要3s,),所以不会提取该任务的回调函数去执行。等到3s之后,异步处理有结果了,立即将其回调提取到执行栈中执行。
(8)在sleepFirstTask中执行了this.next(),taskList中的第一个task,也就是eatAppleTask被执行。……
function LazyMan(name) {
const task = [];
this.eat = (food) => {
const fn = () => {
console.log("I am eating", food);
this.run();
};
task.push(fn);
return this;
};
this.sleep = (t) => {
const fn = () => {
setTimeout(() => {
console.log(`等待了${t}秒...`);
this.run();
}, t * 1000);
};
task.push(fn);
return this;
};
this.sleepFirst = (t) => {
const fn = () => {
setTimeout(() => {
console.log(`等待了${t}秒...`);
this.run();
}, t * 1000);
};
task.unshift(fn);
return this;
};
this.run = () => {
const fn = task.shift();
fn && fn();
};
setTimeout(() => {
this.run();
}, 0);
console.log("Hi I am", name);
return this;
}
看了半天发现大家都是用队列来做的吗- -
`class LazyManFactory {
constructor(name) {
this.name = name
this.sayHi()
this.sleepTime = 0
}
sayHi () {
console.log(`Hi I am ${this.name}`)
}
sleep (time) {
process.nextTick(() => {
this.sleepTime += time * 1000
setTimeout(() => console.log(`等待了${time}秒...`), this.sleepTime)
})
return this
}
eat (type) {
process.nextTick(() => {
setTimeout(() => {
this.saySomething('eating', type)
}, this.sleepTime)
})
return this
}
sleepFirst (time) {
this.sleepTime += time * 1000
setTimeout(() => console.log(`等待了${time}秒...`), this.sleepTime)
return this
}
saySomething (action, type) {
console.log(`I am ${action} ${type}`)
}
}
function LazyMan (name) {
return new LazyManFactory(name)
}
// LazyMan('Tony');
// Hi I am Tony
// LazyMan('Tony').sleep(10).eat('lunch');
// // Hi I am Tony
// // 等待了10秒...
// // I am eating lunch
// LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// // Hi I am Tony
// // I am eating lunch
// // 等待了10秒...
// // I am eating diner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food`
class LazyManClass{
constructor(name){
this.next = null
this.cb = () => {}
}
eat(name){
return this.delay(0, () => console.log(name))
}
sleep(during = 0){
return this.delay(during)
}
sleepFirst(during = 0){
return this.delay(during)
}
delay(during, callback){
this.next = new LazyManClass()
this.cb = () => setTimeout(() => {
callback && callback()
this.next && this.next.cb()
}, during * 1000);
return this.next
}
start(){
setTimeout(() => this.cb(), 0);
return this
}
}
function LazyMan(name){
console.log("Hi I am " + name)
return new LazyManClass().start()
}
class LazyManClass {
constructor(name) {
this.taskList = [];
this.sayName(name);
setTimeout(() => {
this.start();
}, 0)
}
eat(food) {
this.taskList.push(() => {
console.log(`Hi I eating ${food}`)
const fn = this.taskList.shift();
fn && fn();
})
return this;
}
sleep(time) {
this.taskList.push(((time) => {
return () => {
setTimeout(() => {
console.log(`等待了${time / 1000}秒`)
const fn = this.taskList.shift();
fn && fn();
}, time)
}
})(time * 1000))
return this;
}
sleepFirst(time) {
this.taskList.unshift(((time) => {
return () => {
setTimeout(() => {
console.log(`等待了${time / 1000}秒`)
const fn = this.taskList.shift();
fn && fn();
}, time)
}
})(time * 1000))
return this;
}
sayName(name) {
console.log(`Hi I am ${name}`)
}
start() {
const fn = this.taskList.shift();
fn && fn();
}
}
function LazyMan(name) {
return new LazyManClass(name);
}
//LazyMan('Tony');
// Hi I am Tony
//LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
//LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
class People { constructor(name) { this.name = name; this.fns = []; this.fns.push({ m: 0, fn: () => { this.print('i am ' + name); } }) setTimeout(()=>{ this.run(); }) } print(str) { console.log(str); } run(){ if(this.fns.length){ const item = this.fns.shift(); if(item.m){ item.fn(); item.fn = null; } setTimeout(()=>{ item.fn && item.fn(); this.run(); },item.m) } } eat(str){ this.fns.push({m:0,fn:()=>{ this.print(str); }}) return this; } sleep(num){ this.fns.push({ m:num, fn:()=>{ this.print('延迟了'+num+'秒。。。'); } }) return this; }
sleepFirst(num){ this.fns.splice(1,0,{ m:num, fn:()=>{ this.print('延迟了'+num+'秒。。。'); } }) return this; } } new People('phillip').eat('dinner').eat('hahaha').sleepFirst(1000).sleep(2000).eat('lunch');
class LazyManClass {
constructor(name) {
console.log(`Hi I am ${name}`);
this.fns = [];
setTimeout(() => {
this.next();
}, 0);
}
eat(food) {
this.fns.push(() => {
console.log(`I am eating ${food}`);
this.next();
});
return this;
}
delay(time) {
return () => {
setTimeout(() => {
console.log(`等待了${time}秒...`);
this.next();
}, 1000 * time);
}
}
sleep(time) {
this.fns.push(this.delay(time));
return this;
};
sleepFirst(time) {
this.fns.unshift(this.delay(time));
return this;
};
next() {
this.fns.length > 0 && this.fns.shift()();
};
}
function LazyMan(name) {
return new LazyManClass(name);
}
function LazyManImpl(name) {
console.log(`Hi I am ${name}`);
this.microQueue = [];
this.macroQueue = [];
this.executionContext = 'NoContext';
}
LazyManImpl.prototype.eat = function (str) {
this.macroQueue.push(() => {
console.log(`I am eating ${str}`);
this.next();
});
this.scheduling();
return this;
};
LazyManImpl.prototype.sleepFirst = function (number) {
this.microQueue.push(() => {
setTimeout(this.next.bind(this), number * 1000);
});
this.scheduling();
return this;
};
LazyManImpl.prototype.sleep = function (number) {
this.macroQueue.push(() => {
setTimeout(this.next.bind(this), number * 1000)
});
this.scheduling();
return this;
};
LazyManImpl.prototype.next = function () {
if (this.executionContext !== 'RunContext') return;
if (this.microQueue.length > 0) {
const fn = this.microQueue.shift();
fn();
} else if (this.macroQueue.length > 0) {
const fn = this.macroQueue.shift();
fn();
} else {
this.executionContext = 'NoContext';
}
};
LazyManImpl.prototype.scheduling = function () {
switch (this.executionContext) {
case 'RunContext':
this.next();
break;
case 'NoContext':
this.executionContext = 'RegisterContext';
setTimeout(function () {
this.executionContext = 'RunContext';
this.next();
}.bind(this), 0);
break;
case 'RegisterContext':
break;
default:
// TODO warning
break;
}
};
const LazyMan = name => new LazyManImpl(name);
// LazyMan('Tony');
// LazyMan('Tony').sleep(10).eat('lunch');
// LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
class LazyManClass {
constructor(name) {
this.name = name
this.sleepFirstAmount = 0
this.queue = []
Promise.resolve().then(() => {
this.run()
})
}
async run() {
this.hello(this.name)
if(this.sleepFirstAmount > 0) {
await new Promise((resolve) => {
setTimeout(resolve, this.sleepFirstAmount * 1000)
})
}
while(this.queue.length) {
const task = this.queue.shift()
const type = task.type
const value = task.value
if(type === 'eat') {
console.log(value)
continue
}
if (type === 'sleep') {
await new Promise((resolve) => { setTimeout(resolve, value * 1000) })
}
}
}
hello(name) {
console.log(name)
}
sleep(second) {
this.queue.push({type: 'sleep', value: second})
return this
}
sleepFirst(second) {
this.sleepFirstAmount += second
return this
}
eat(food) {
this.queue.push({type: 'eat', value: food})
return this
}
}
function LazyMan(name) {
return new LazyManClass(name)
}
LazyMan('Nathan').eat('apple').sleep(5).sleepFirst(3).eat('water')
function Man(name){
this.name = `Hi I am ${name}`
this.str = []
this.time = setTimeout(()=>{
this.parse()
},0)
}
Man.prototype.sleep = function(minutes){
this.str.push(`等待了${minutes}秒`)
clearTimeout(this.time)
this.time = setTimeout(()=>{
this.parse()
},0)
return this
}
Man.prototype.eat = function(food){
this.str.push(`I am eating ${food}`)
clearTimeout(this.time)
this.time = setTimeout(()=>{
this.parse()
},0)
return this
}
Man.prototype.sleepFirst = function(minutes){
this.str.unshift(`等待了${minutes}秒`)
clearTimeout(this.time)
this.time = setTimeout(()=>{
this.parse()
},0)
return this
}
Man.prototype.parse = function(){
console.log(this.name+'\n'+this.str.join('\n'))
}
function LazyMan(name){
return new Man(name)
}