带你看看webpack中的异步任务调度

先贴图:
在这里插入图片描述

带大家一步一步完成这个代码,第一步就是有个异步类,该类包括调度的名称、调度的执行函数、同时执行的任务个数、当前正在执行的个数、剩余任务队列:

const quene = new asyncQuene({
	name: 'addNumber',
	process,
	limit: 2
})
constructor(options) {
	// 调度的名称
	this.name = options.name
	// 调度的执行函数
	this.process = options.process
	// 同时执行的任务个数
	this.limit = options.limit
	// 用来判断是否同一个任务
	this.entries = new Map()
	// 剩余任务队列
	this.quened = []
	// 当前正在执行的个数
	this.activeTasks = 0
	// 是否开始下一次循环
	this.startNextLoop = true
}

然后该调度还能添加任务:

quene.add({
	key: 1
}, (err, res) => {
	console.log('1的处理结果');
})
quene.add({
	key: 2
}, (err, res) => {
	console.log('2的处理结果');
})
quene.add({
	key: 1
}, (err, res) => {
	console.log('1的处理结果' );
})
quene.add({
	key: 3
}, (err, res) => {
	console.log('3的处理结果');
})

添加的任务第一个是对象,第二个是执行完成的回调。
可以得到类有个添加的方法:

  1. 添加任务
add(item, callback) {
	const newEntry = {
		item,
		callback,
		state: 0,
		result: null,
		error: null,
		callbacks:null
	}
	const key = item.key
	const entry = this.entries.get(key)
	if (entry) {
		// 前面相同的已经执行完毕
		if (entry.state === 2) {
			callback(entry.error, entry.result)
		} else if (!entry.callbacks) {
		    // 如果没有callbacks
			entry.callbacks = [callback]
		} else {
		   // 前面的还没执行完毕
			entry.callbacks.push(callback)
		}
		return;
	}
	this.entries.set(item.key, newEntry)
	// 入栈
	this.quened.push(newEntry)
	// 需要开启下一个回调
	if (this.startNextLoop) {
		// 1.这里异步是要先添加所有任务再开始处理 2.startNextLoop作用是控制不会每个任务都立马执行
		Promise.resolve().then(() => {
			this.startTasks()
		})
		this.startNextLoop = false
	}
}
  1. 开始执行任务
startTasks() {
	// 会一个个处理队列对象,直到limit
	while (this.activeTasks < this.limit) {
		// 获取任务
		const target = this.quened.shift()
		if (!target) break
		// 当前执行数加一
		this.activeTasks++
		target.state = 1
		// 执行处理函数,并将处理结果回调并进入handleRes
		this.process(target.item, (err, res) => {
			this.handleRes(target, err, res)
		})
	}
	// 处理完这一轮才能开始下一轮
	this.startNextLoop = true
}
  1. 处理回调结果
handleRes(entry, err, res) {
	const callback = entry.callback
	const callbacks = entry.callbacks
	entry.state = 2
	entry.result = res
	entry.error = err
	// 当前进行的任务减一
	this.activeTasks--
	// 执行任务执行完毕的回调
	callback(err, res)
	// 如果有同样的key值的会放入callbacks,此时就可以执行所有的回调
	if (callbacks) {
		for (const callback of callbacks) {
			callback(err, res);
		}
	}
	// 如果startNextLoop为true表示要开始下一波循环,每次执行完一个任务都要判断
	// 是否要进入下一波循环
	if (this.startNextLoop) {
		Promise.resolve().then(() => {
			this.startTasks()
		})
		this.startNextLoop = false
	}
}
const process = (item, callback) => {
	setTimeout(function() {
		callback(null, item)
	}, 1000)
}

完整代码如下:

class asyncQuene {
	constructor(options) {
		this.name = options.name
		this.process = options.process
		this.limit = options.limit
		this.entries = new Map()
		this.quened = []
		this.activeTasks = 0
		this.startNextLoop = true
	}

	add(item, callback) {
		const newEntry = {
			item,
			callback,
			state: 0,
			result: null,
			error: null,
			callbacks:null
		}
		const key = item.key
		const entry = this.entries.get(key)
		if (entry) {
			if (entry.state === 2) {
				callback(entry.error, entry.result)
			} else if (!entry.callbacks) {
				entry.callbacks = [callback]
			} else {
				entry.callbacks.push(callback)
			}
			return;
		}
		this.entries.set(item.key, newEntry)
		this.quened.push(newEntry)
		this.startLoop()
	}
	startLoop() {
	    // 处理完这一轮,开始下一轮
	    if (this.startNextLoop) {
	      Promise.resolve().then(() => {
	        this.startTasks()
	      })
	      this.startNextLoop = false
	    }
	  }

	startTasks() {
		while (this.activeTasks < this.limit) {
			const target = this.quened.shift()
			if (!target) break
			this.activeTasks++
			target.state = 1
			this.process(target.item, (err, res) => {
				this.handleRes(target, err, res)
			})
		}
		this.startNextLoop = true
	}

	handleRes(entry, err, res) {
		const callback = entry.callback
		const callbacks = entry.callbacks
		entry.state = 2
		entry.result = res
		entry.error = err
		this.activeTasks--
		callback(err, res)
		if (callbacks) {
			for (const callback of callbacks) {
				callback(err, res);
			}
		}
		this.startLoop()
	}
}
const quene = new asyncQuene({
	name: 'addNumber',
	process,
	limit: 2
})

quene.add({
	key: 1
}, (err, res) => {
	console.log('1的处理结果' + res.number);
})
quene.add({
	key: 2
}, (err, res) => {
	console.log('2的处理结果');
})
quene.add({
	key: 1
}, (err, res) => {
	console.log('1的处理结果' + res.number);
})
quene.add({
	key: 3
}, (err, res) => {
	console.log('3的处理结果');
})

在这里插入图片描述
给大家几个问题:

  1. add方法最后不用微任务会怎样?
    不用微任务那么如果有多次add,那么只会执行一次。因为第一个add添加完就开始执行了,startNextLoop已经是false,此时会再次执行add方法,但是startNextLoop为false就不会进入startTasks,所以不用微任务就只会执行一次
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Young soul2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值