首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >创建循环的异步实例并管理它们

创建循环的异步实例并管理它们
EN

Stack Overflow用户
提问于 2022-11-03 08:30:09
回答 1查看 53关注 0票数 0

我使用一个chrome扩展来激活无限的循环异步实例,这样它们就不会相互冲突。

有一个值列表,并将一个项传递给每个单独的循环。这些循环在content.js中执行,由background.js管理,但它们是从popup.js中初始化、启动和取消的。

现在的大问题是如何使用最佳实践来使多异步循环的管理尽可能容易?有没有任何可能的方法也取消这些循环以一种简单的方式?

示例代码:

content.js:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-03 10:59:47

您可能应该使用图书馆

...but,那会很无聊的!

在下面的代码中,macrotask使用requestIdleCallback对JS运行时宏任务运行回调。

用户提供要处理的数据、每一步运行的逻辑(同步)和延续条件;他们不必担心显式地屈服于API。

函数createTask构造一个生成器来返回步骤,直到continuationPredicate返回false为止。生成器功能使我们能够挂起并恢复同步代码--在这里我们需要这样做,以便以循环的方式在任务之间切换。更高级的解决方案可以根据启发式将任务排序。

createCircularList返回一个用于公开addremovenext的数组的包装器(按创建顺序获取下一项,或者,如果处于“末尾”,则再次循环到第一项)。

createScheduler维护任务列表。当任务列表中仍有任务时,此函数将标识下一个任务,将其下一步安排在宏任务上,并等待该步骤完成。如果这是当前任务的最后一步,则任务将从任务列表中删除。

请注意,这段代码的输出的精确交织将取决于机器有多忙。演示的目的是展示如何在任务队列耗尽时添加任务队列。

代码语言:javascript
运行
复制
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 

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74300045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档