Open liuzhengbo opened 6 years ago
function LazyMan(name) {
var tasks = []
var obj = function() {
return obj
}
function add(task) {
tasks.push(task)
}
function sort() {
return tasks.sort((a, b) => {
return a.weight < b.weight
})
}
function flush() {
sort()
tasks.map((task) => {
task.handler()
})
}
function sleepFn(time) {
var end = +new Date() + time * 1000
while(true) {
var now = +new Date()
if(now > end) {
console.log(`Wake up after ${time}`)
return
}
}
}
obj.init = function() {
add({
name: 'init',
weight: 0,
handler: function() {
console.log(`Hi! This is ${name}!`)
}
})
}
obj.sleep = function(time) {
add({
name: 'sleep',
weight: 0,
handler: function() {
sleepFn(time)
}
})
return this
}
obj.eat = function(something) {
add({
name: 'eat',
weight: 0,
handler: function() {
console.log(`Eat ${something}`)
}
})
return this
}
obj.sleepFirst = function(time) {
add({
name: 'sleepFirst',
weight: 1,
handler: function() {
sleepFn(time)
}
})
return this
}
obj.toString = function() {
return setTimeout(() => {
flush()
})
}
obj.init()
return obj
}
function LazyMan(name) {
return new LazyMan_(name)
}
function LazyMan_(name) {
this.tasks = [`sayHi`]
this.counter = 0
this.name = name
this.promise = Promise.resolve().then(() => {
this._startTasks()
})
}
LazyMan_.prototype._startTasks = function() {
let setPromiseOnce = false;
let ts = this.tasks
let promiseTaskNames = 'sleep|sleepFirst';
for (let i = this.counter; i < ts.length; i++) {
let tmp = ts[i].split('|')
if (!promiseTaskNames.includes(tmp[0])) {
this.promise.then(() => {
let name = `_${tmp[0]}`
this[name](tmp[1])
})
} else if (!setPromiseOnce && promiseTaskNames.includes(tmp[0])) {
let name = `_${tmp[0]}`
this[name](tmp[1])
setPromiseOnce = true
} else {
this.promise.then(() => {
this._startTasks();
})
this.counter = i
break;
}
}
return this
}
LazyMan_.prototype._addTask = function(name, value) {
let task = name + (value ? `|${value}` : '')
this.tasks.push(task);
return this
}
LazyMan_.prototype._sayHi = function() {
console.log(`Hi! This is ${this.name}!`)
return this
}
LazyMan_.prototype.eat = function(sth) {
this._addTask('eat', sth);
return this
}
LazyMan_.prototype._eat = function(sth) {
console.log(`Eat ${sth}`)
return this
}
LazyMan_.prototype.sleep = function(secondNum) {
this._addTask('sleep', secondNum)
return this
}
LazyMan_.prototype.sleepFirst = function(secondNum) {
this.tasks.unshift(`sleepFirst|${secondNum}`)
return this
}
LazyMan_.prototype._sleep = function(secondNum) {
this.promise = new Promise(resolve => {
setTimeout(resolve, secondNum * 1000)
})
this.promise.then(() => console.log(`Wake up after ${secondNum}`))
return this
}
LazyMan_.prototype._sleepFirst = function(secondNum) {
return this._sleep(secondNum)
}
LazyMan('Hank').sleep(2).eat('dinner').sleep(3).eat('supper').sleepFirst(1)
function LazyMan(name) {
if (!(this instanceof LazyMan)) {
return new LazyMan(name)
}
this.queue = [{value: `Hi! This is ${name}!`}]
setTimeout(() => { this.next() })
}
Object.assign(LazyMan.prototype, {
sleep (time) {
this.queue.push({value: `Wake up after `, delay: time * 1000})
return this
},
sleepFirst (time) {
this.queue.unshift({value: `Wake up after `, delay: time * 1000})
return this
},
eat (val) {
this.queue.push({value: `Eat ${val}~`})
return this
},
next () {
if (this.queue.length) {
let item = this.queue.shift()
setTimeout(() => {
console.log(item.value)
this.next()
}, item.delay || 0)
}
}
})
LazyMan('Hank').sleepFirst(0.5).eat('supper').sleep(1)
const next = async function () {
if (this.tasks.length) {
const task = this.tasks.shift();
task && await task();
}
}
class LazyManImpl {
constructor(name) {
this.tasks = [];
this.tasks.push(() => {
console.log(`Hi! This is ${name}!`);
next.apply(this);
});
setTimeout(() => {
next.apply(this)
}, 0)
}
eat(food) {
this.tasks.push(() => {
console.log(`Eat ${food}~`);
next.apply(this);
})
return this;
}
sleep(ts) {
this.tasks.push(() => {
setTimeout(() => {
console.log(`Wake up after ${ts}`);
next.apply(this);
}, ts * 1000)
});
return this;
}
sleepFirst(ts) {
this.tasks.unshift(() => {
setTimeout(() => {
console.log(`Wake up after ${ts}`);
next.apply(this);
}, ts * 1000);
})
return this;
}
}
const LazyMan = function (name) {
return new LazyManImpl(name)
}
function _LazyMan(name) {
var _this = this;
_this.fnArray = [];
var fn =(function(n){
return function(){
console.log('Hi! This is ' + n + '!');
_this.next();
}
})(name);
_this.fnArray.push(fn);
setTimeout(function(){
_this.next();
}, 0);
}
_LazyMan.prototype = {
next: function () {
var fn = this.fnArray.shift();
fn && fn();
},
eat: function (str) {
var _this = this;
var fn = (function(s){
return function(){
console.log('Eat ' + s + '~');
_this.next()
}
})(str);
_this.fnArray.push(fn);
return _this;
},
sleep: function (time) {
var _this = this;
var fn = (function(t){
return function(){
setTimeout(function(){
console.log('Wake up after ' + t);
_this.next();
}, t * 1000);
}
})(time);
_this.fnArray.push(fn);
return _this;
},
sleepFirst: function (time) {
var _this = this;
var fn = (function(t){
return function() {
setTimeout(function() {
console.log('Wake up after ' + t);
_this.next();
}, t * 1000);
}
})(time);
_this.fnArray.unshift(fn);
return _this;
}
}
function LazyMan(name){
return new _LazyMan(name);
}
LazyMan('Hank').sleep(2).eat('dinner')
实现一个LazyMan,可以按照以下方式调用:
以此类推。