实现一个LazyMan你可以学到,链式调用、class、同步异步、Promise、回调函数、箭头函数。
可以按照以下方式调用:
/**
LazyMan(“Hank”)输出:
Hi! This is Hank!
LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
Hi! This is Hank!
//等待10秒..
Wake up after 10
Eat dinner~
LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出
Hi This is Hank!
Eat dinner~
Eat supper~
LazyMan(“Hank”).eat(“supper”).sleepFirst(5)输出
//等待5秒
Wake up after 5
Hi This is Hank!
Eat supper
*/
主要的实现思路是,第一步先class 一个对象,在construstor 函数初始化一个callBacks 数组,再去class里写入对应的方法,方法里面写入需要的延迟函数,或者是不需要延迟的函数。每当链式调用把this返回出去this就是当前的class方便下次在进行调用,把每一个延迟函数放到callBacks数组当中。然后在去循环callBacks数组,以同步的方式进行调用这样不管你的函数延迟多少秒,当延迟函数不走完下一个函数是不会进行的。这就是大概的实现思路。
1.定义class 写一个callbacks 数组
class _LazyMan {
constructor(name) {
this.callbacks = []
}
}
2.将callbacks数组同步进行执行,循环同步执行代码。
class _LazyMan {
constructor(name) {
this.callbacks = []
// 循环同步执行代码
setTimeout(async () => {
for (let i = 0; i < this.callbacks.length; i++) {
const fn = this.callbacks[i]
await fn()
}
})
}
}
3.输出方法开始 LazyMan('Hank') // Hi This is Hank!
class _LazyMan {
constructor(name) {
this.callbacks = []
// 第一次实例hua调用函数执行
const task = () => {
this.say(name)
}
this.callbacks.push(task) // 初始化放一个函数
setTimeout(async () => { // 循环同步执行 延迟函数不走完下一个函数是不会走的。
for (let i = 0; i < this.callbacks.length; i++) {
const fn = this.callbacks[i]
await fn()
}
})
}
say (name) {
console.log(` Hi This is ${name}!`)
return this
}
}
function LazyMan (name) {
return new _LazyMan(name)
}
LazyMan('Hank') // Hi This is Hank!
为什么不用forEach循环进行async呢?因为forEach不支持这样操作,原因callback 其实是我们传入的一个被 async 封装的 promise 对象,而 Array.prototype.forEach 内部并未对这个promise 对象做任何处理,foreach的实现并没有return 返回值,只是忽略它。可以去github看看forEach的源码。forEach 只支持同步,不支持异步。
4.输出方法开始 LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
class _LazyMan {
constructor(name) {
this.callbacks = []
const task = () => {
this.say(name)
}
this.callbacks.push(task)
setTimeout(async () => {
for (let i = 0; i < this.callbacks.length; i++) {
const fn = this.callbacks[i]
await fn()
}
})
}
say (name) {
console.log(` Hi This is ${name}!`)
return this
}
eat (food) {
const task = () => {
console.log(`Eat ${food}~`)
}
this.callbacks.push(task)
return this
}
// 阻塞time * 1000秒后在执行下面的任务
sleep (time) {
const task = () => {
// 返回一个新的 promise 对象
return new Promise((resolve) => {
setTimeout(resolve, time * 1000)
})
.then(() => {
console.log(`Wake up after ${time}`)
})
}
// callbacks 放入延迟执行函数
this.callbacks.push(task)
//重新返回 _LazyMan 为了后续继续链式调用
return this
}
}
function LazyMan (name) {
return new _LazyMan(name) // 实例化_LazyMan方法
}
LazyMan('Hank').sleep(10).eat('dinner')// Hi This is Hank! Wake up after 10 Eat dinner~
LazyMan('Hank').eat('dinner').eat('supper') // Hi This is Hank! Eat dinner~ Eat supper~
5.输出方法开始LazyMan(“Hank”).eat(“supper”).sleepFirst(5)输出
完整版本
class _LazyMan {
constructor(name) {
this.callbacks = []
const task = () => {
this.say(name)
}
this.callbacks.push(task)
setTimeout(async () => {
for (let i = 0; i < this.callbacks.length; i++) {
const fn = this.callbacks[i]
await fn()
}
})
}
say (name) {
console.log(` Hi This is ${name}!`)
return this
}
eat (food) {
const task = () => {
console.log(`Eat ${food}~`)
}
this.callbacks.push(task)
return this
}
// 阻塞time * 1000秒后在执行下面的任务
sleep (time) {
const task = () => {
return new Promise((resolve) => {
setTimeout(resolve, time * 1000)
})
.then(() => {
console.log(`Wake up after ${time}`)
})
}
this.callbacks.push(task)
return this
}
// 先阻塞time * 1000秒后在依次执行任务
sleepFirst (time) {
const task = () => {
return new Promise((resolve) => {
setTimeout(resolve, time * 1000)
})
.then(() => {
console.log(`Wake up after ${time}`)
})
}
this.callbacks.unshift(task) //只要调用sleepFirst就把函数放到第一个执行
return this
}
}
function LazyMan (name) {
return new _LazyMan(name)
}
// LazyMan('Hank')
// LazyMan('Hank').sleep(10).eat('dinner')
// LazyMan('Hank').eat('dinner').eat('supper')
LazyMan('Hank').eat('supper').sleepFirst(5)
我是阿豪