实现 Hardman 函数
要求:
HardMan("jack")
// > I am jack
HardMan("jack").rest(10).learn("computer")
// > I am jack
// 等待10秒
// > Start learning after 10 seconds
// > Learning computer
HardMan("jack").restFirst(5).learn("chinese")
// 等待5秒
// > Start learning after 5 seconds
// > I am jack
// > Learning chinese
上文中 [ > … ] 表示打印内容。
挺有意思的,但是解不了,就来问问
function HardMan(name) {
function introduce() {
console.log(`I am ${name}`)
}
let first = 0
let delay = 0
let timer = setTimeout(introduce, 0)
return Object.create({
rest(time) {
delay += time * 1000
return this
},
restFirst(time) {
clearTimeout(timer)
first += time * 1000
timer = setTimeout(function () {
console.log(`Start learning after ${time} seconds`)
console.log(`I am ${name}`)
}, first)
return this
},
learn(lessen) {
setTimeout(function () {
console.log(`Learning ${lessen}`)
}, delay + first)
return this
}
})
}
以上代码可以实现当前要求
推测考察的是对eventloop的理解吧
但是rest
和restFirst
如果多次调用就不知道了 要求里没有体现
刚写完,发现楼上已经发出答案了。比自己写的简单多了。就不贴代码了。向楼上学习。
@Zero2key 考什么我就不知道了,不过你的答案能实现要求就是了。我也贴一下找到的另一个答案,可以实现多次 rest
const HardMan = function (name) {
this.tasks = [
() => console.log(`I am ${name}`)
];
this.rest = function (time) {
this.tasks.push(this.sleep(time));
return this;
}
this.restFirst = function (time) {
this.tasks.unshift(this.sleep(time));
return this;
}
this.learn = function (something) {
this.tasks.push(() => console.log('Learning ' + something));
return this;
}
this.sleep = function (time) {
return () => new Promise(resolve => setTimeout(() => {
resolve(console.log(`Start learning after ${time} second`));
}, time * 1000));
}
this.run = function () {
setTimeout(async () => {
for (task of this.tasks) {
await task();
}
}, 0);
return this;
}
return this.run();
}
@hfuuss 也学习一下这个。
function HardMan(name) {
var tasks = [];
var after = 0;
var next = function () {
if (tasks.length) (tasks.shift())();
};
var sleep = function (time) {
return function () {
setTimeout(function () {
after += time;
console.log(`Start learning after ${after} second`);
next();
}, time * 1000);
};
};
var fn = function () { };
fn.prototype.rest = function (time) {
tasks.push(sleep(time));
return this;
};
fn.prototype.restFirst = function (time) {
tasks.unshift(sleep(time));
return this;
};
fn.prototype.learn = function (subject) {
tasks.push(function () {
console.log(`Learning ${subject}`);
after = 0;
next();
});
return this;
};
tasks.push(function () {
console.log(`I am ${name}`);
after = 0;
next();
});
setTimeout(next, 0);
return new fn();
}
HardMan("jack").rest(2).learn("chinese").rest(3).learn("computer").restFirst(1);
let HardMan = function(name){
let firstRestTime = false, restTime = false, theThing = '';
function C(e){ console.log(e); }
setTimeout(()=>{
if(firstRestTime === 0 || firstRestTime){
setTimeout(()=>{
C('Start learning after '+ firstRestTime +' seconds');
C('I am '+name);
C('Learning ' + theThing);
},firstRestTime * 1000);
}else if(restTime === 0 || restTime){
C('I am ' + name);
setTimeout(()=>{
C('Start learning after '+restTime+' seconds');
C('Learning '+ theThing);
},restTime * 1000);
}else{
C('I am '+name);
}
},0);
return {
rest(time){
restTime = time;
return this;
},
learn(thing){
theThing = thing;
return this;
},
restFirst(time){
firstRestTime = time;
return this;
}
}
}
var HardMan = function (name) {
var promise = function (timer, text) {
return new Promise((resolve, reject) => {
if (timer) {
setTimeout(() => {
resolve(text);
}, timer);
return;
}
reject(text);
});
};
class Foo {
constructor(name) {
this.name = name;
this.delay = 0;
this.result = [];
this.result.push({ time: this.delay, text: `I am ${name}` });
setTimeout(() => {
var isTime = 0;
this.result.forEach(item => {
isTime = item.time || isTime;
promise(item.time || isTime, item.text)
.then(console.log)
.catch(console.log);
});
}, 0);
}
rest(time) {
this.delay = time * 1000;
this.result.push({ time: this.delay, text: `Start learning after ${time} seconds` });
return this;
}
learn(name) {
this.result.push({ time: this.delay, text: `Learning ${name}` });
return this;
}
restFirst(time) {
this.delay = time * 1000;
this.result.unshift({ time: this.delay, text: `Start learning after ${time} seconds` });
return this;
}
}
return new Foo(name);
};
aop 切片 实现
@Littlesqx 这个思路是对的,正如六楼要的----最后还能restFirst,所以是用一个任务队列来存储这些调用。 首先构造函数把介绍自己的任务压入队列,然后在下一个事件循环开始时,取出并执行队列第一个任务。 每一个方法都会把”自己的功能+调用队列下一个任务“包装成任务,压入队列中。有点像restify中间件的调用。 值得说的是restfirst方法需要把任务弄到队列头部。
贴出我自己写的有注释版本:
function HardMan(name) {
var Man = function (name) {
// 存自己的名字
this.name = name
// 任务队列
this.queue = []
// 把介绍自己的方法入列
this.me()
// 下个事件循环开始调用队列
setTimeout(() => {
this.callNext()
}, 0)
}
Man.prototype = {
// 取出队列顶部函数,调用
callNext: function() {
if(this.queue.length)
this.queue.shift()()
},
// 介绍自己,普通任务,
me: function () {
var ii = () => {
console.log('I am ' + this.name)
this.callNext()
}
this.queue.push(ii)
},
// 休息,直接把延时函数压入队列,定时结束后再调用队列下一个任务
rest: function(sec) {
var ii = () => {
setTimeout(()=>{
console.log(`after ${sec} secs`)
this.callNext()
}, sec * 1000)
}
this.queue.push(ii)
return this
},
// 同理,只是任务放到队列顶部,
restFirst: function(sec) {
var ii = () => {
setTimeout(()=>{
console.log(`after ${sec} secs`)
this.callNext()
}, sec * 1000)
}
this.queue.unshift(ii)
return this
},
// 普通任务
learn: function(course) {
var ii = () => {
console.log(`learn ${course}`)
this.callNext()
}
this.queue.push(ii)
return this
}
}
Man.prototype.constructor = Man
return new Man(name)
}
HardMan("jack").rest(2).learn("chinese").rest(3).learn("computer").restFirst(1)
看来只有我想复杂了。。。用的promise来实现,原来一个队列就可以解决的事
一个简洁的实现,支持随意重复调用rest/restFirst/learn(把restart也放进去只是为了让后面少一行代码)
function HardMan (name) {
const sleep = sec => new Promise(res => setTimeout(res, sec * 1000));
const queue = [() => console.log(`I am ${name}`)];
let timer;
return Object.create({
restart() {
clearTimeout(timer);
timer = setTimeout(() => queue.reduce((p, t) => p.then(t), Promise.resolve()));
return this;
},
rest(time) {
queue.push(async () => sleep(time));
return this.restart();
},
restFirst(time) {
queue.unshift(async () => (await sleep(time)) || console.log(`Start learning after ${time} second`));
return this.restart();
},
learn(sth) {
queue.push(() => console.log(`Learning ${sth}`));
return this.restart();
},
});
}
景安拼团活动,云服务器96元/年。原价960 活动链接:http://server.zzidc.com/pintuan.html