我使用一个chrome扩展来激活无限的循环异步实例,这样它们就不会相互冲突。
有一个值列表,并将一个项传递给每个单独的循环。这些循环在content.js中执行,由background.js管理,但它们是从popup.js中初始化、启动和取消的。
现在的大问题是如何使用最佳实践来使多异步循环的管理尽可能容易?有没有任何可能的方法也取消这些循环以一种简单的方式?
示例代码:
content.js:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if(request.message.active){
console.log("do something");
dispatch(request.message);
}});
async function dispatch(alternator) {
if (alternator.active) {
await new Promise(resolve => setTimeout(resolve, alternator.timeout));
console.log("do something");
}
return;
}
这个background.js应该在数组中有一个要管理的异步循环列表,或者一些易于管理的东西。for-循环消耗了太多的时间,超时导致了太多的负载。
background.js
async function dispatchBackground() {
while (1) {
for (let i = 0; i < alternator.length; i++) {
if(alternator[i].active){
chrome.tabs.sendMessage(alternator[i].tab_id, {"message": alternator[i]});
}
}
await new Promise(resolve => setTimeout(resolve, 100));
}
return;
}
发布于 2022-11-03 10:59:47
您可能应该使用图书馆。
...but,那会很无聊的!
在下面的代码中,macrotask
使用requestIdleCallback
对JS运行时宏任务运行回调。
用户提供要处理的数据、每一步运行的逻辑(同步)和延续条件;他们不必担心显式地屈服于API。
函数createTask
构造一个生成器来返回步骤,直到continuationPredicate
返回false为止。生成器功能使我们能够挂起并恢复同步代码--在这里我们需要这样做,以便以循环的方式在任务之间切换。更高级的解决方案可以根据启发式将任务排序。
createCircularList
返回一个用于公开add
、remove
和next
的数组的包装器(按创建顺序获取下一项,或者,如果处于“末尾”,则再次循环到第一项)。
createScheduler
维护任务列表。当任务列表中仍有任务时,此函数将标识下一个任务,将其下一步安排在宏任务上,并等待该步骤完成。如果这是当前任务的最后一步,则任务将从任务列表中删除。
请注意,这段代码的输出的精确交织将取决于机器有多忙。演示的目的是展示如何在任务队列耗尽时添加任务队列。
const log = console.log
const nop = () => void 0
const stepPerItem = (_, i, data) => i < data.length
const macrotask = (cb) => (...args) => new Promise((res) => (typeof requestIdleCallback ? requestIdleCallback : setTimeout)(() => res(cb(...args))))
const createTask = (data,
step,
continuePredicate = stepPerItem,
acc = null,
onDone = nop) =>
(function*(i = 0) {
while(continuePredicate(acc, i, data)) {
acc = step(acc, i, data)
yield [acc, onDone]
i++
}
return [acc, onDone]
})()
const createCircularList = (list = []) => {
const add = list.push.bind(list)
const remove = (t) => list.splice(list.indexOf(t), 1)
const nextIndex = (curr, currIndex = list.indexOf(curr)) =>
(currIndex === list.length - 1) ? 0 : currIndex + 1
const next = (curr) =>
list.length ? list[nextIndex(curr)] : null
return { add, remove, next }
}
const createScheduler = (tasks = createCircularList()) => {
let isRunning = false
const add = (...tasksToAdd) =>
(tasksToAdd.forEach((t) => tasks.add(t)),
!isRunning && (isRunning = true, go()))
const remove = tasks.remove.bind(tasks)
const go = async (t = null) => {
while(t = tasks.next(t))
await macrotask(({ done, value: [result, onDone] } = t.next()) =>
done && (tasks.remove(t), onDone(result)))()
isRunning = false
}
return { add, remove }
}
const scheduler = createScheduler()
const task1 = createTask([...Array(5)], (_, i) => log('task1', i))
const task2 = createTask([...Array(5)], (_, i) => log('task2', i))
const task3 = createTask([...Array(5)], (_, i) => log('task3', i))
scheduler.add(task1, task2)
setTimeout(() => scheduler.add(task3), 50) // you may need to fiddle with the `setTimeout` delay here to observe meaningful interleaving
https://stackoverflow.com/questions/74300045
复制相似问题