前端小技巧: 写一个异步程序示例, 使用任务队列替代promise和async/await等语法糖
异步程序设定场景
1 )场景设定
- 可以使用懒人每做几件事,就要休息一会儿,并且不会影响做事的顺序这种场景来模拟
- 定义单例名称为: lazyMan
- 支持 sleep 和 eat 两个方法
- 支持链式调用
2 ) 调用示例
const lm = new LazyMan('www')
lm.eat('苹果').eat('香蕉').sleep(5).eat('葡萄')
分析与设计
- 上述是基于异步实现一个"懒人做事"的调用过程
- 设计
- 由于有sleep功能,函数不能直接在调用时触发
- 初始化一个列表,把函数注册进去
- 由每个item触发next执行(遇到sleep则异步触发)
代码实现
lazyMan.ts 代码如下
class LazyMan {
private name: string
private tasks: Function[] = [] // 任务列表
constructor(name: string) {
this.name = name
// 这里必须异步触发
const timer = setTimeout(() => {
clearTimeout(timer)
this.next()
})
}
// 用于执行队列中的下一项任务
private next() {
const task = this.tasks.shift() // 取出当前 tasks 的第一个任务
if (task) task()
}
// 定义吃的方法
eat(food: string) {
const task = () => {
console.info(`${this.name} eat ${food}`)
this.next() // 立刻执行下一个任务
}
this.tasks.push(task)
return this // 链式调用
}
// 定义睡的方法
sleep(seconds: number) {
const task = () => {
console.info(`${this.name} 开始睡觉`)
setTimeout(() => {
console.info(`${this.name} 刚刚睡了 ${seconds} s, 正在执行下个任务中 ...`)
this.next() // 异步执行
}, seconds * 1000)
}
this.tasks.push(task)
return this // 链式调用
}
}
const lm = new LazyMan('小王')
lm.eat('苹果').eat('香蕉').sleep(1).eat('葡萄').sleep(2).eat('大米');
- 这里使用任务队列, 异步触发next
- 这个示例是替代promise和async/await的一种方法
- 底层是基于 event loop 机制