javascript上的抢先式后台工作调度的一般解决方案 [英] General solution for pre-emptive background work scheduling on javascript

查看:87
本文介绍了javascript上的抢先式后台工作调度的一般解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是场景: 当我的Web应用程序启动时,我想从本地存储中的几个表中加载数据(使用indexedDB).我将此工作委托给网络工作者.它将依次加载每个表,并在加载每个表时触发一条带有数据的消息.在主线程上,侦听器将接收消息并将数据存储在缓存中.

Here is the scenario: When my web app starts, I want to load data from several tables in local storage (using indexedDB). I delegate this work to a web worker. It will load each table in turn, and fire a message with the data as it loads each one. On the main thread, a listener will receive the message and store the data in a cache.

但是,假设用户按下按钮以查看特定表的数据.该应用程序调用一个函数,该函数检查缓存,并查看该表的数据尚未加载.

But let's say the user presses a button to view the data for a specific table. The app calls a function that checks the cache, and sees that the data for that table has not been loaded yet.

该函数如何等待直到对该表的数据进行缓存后才能返回数据?更重要的是,如果计划将表最后加载,该怎么办?此功能如何将消息发送给网络工作者,以优先考虑加载该特定表,以便尽快获取其数据?

How does this function wait until the data for that table has been cached so that it can return the data? Even more important, what if the table is scheduled to be loaded last? How can this function send a message to the web worker to prioritize loading that specific table so that its data will available as soon as possible?

彻底解决此先发制人调度问题的一般模式是什么?我想尽可能避免轮询.

What is a general pattern for a clean solution to this pre-emptive scheduling problem? I would like to avoid polling if at all possible.

推荐答案

Worker可能使用异步队列,该队列包含所有要加载的表,并按一定的优先级进行排序,因此您可以对某些表进行优先级排序并对其进行排序在桌子的前面.如您尚未显示的实际实现,这里是更通用的版本:

The Worker may use an asynchronous queue that contains all the tables to be loaded and is sorted after a certain priority, so you can priorize certain tables and they get sorted to the front of the table. As you havent shown a real implementation here is a more generalized version:

 class AsyncPriorityQueue {
   constructor(task){
     this.task = task;
     this.queue = [];
   }

   push(element, priority = 0){
     const pos = this.queue.findIndex(el => el.priority < priority) + 1;
     this.queue.splice(pos, 0, {element, priority});

     if(this.running) return;
     this.running = true;
     this._run();
   }

   prioritize(element, priority = 10){
     const pos = this.queue.findIndex(el => el.element === element);
     if(pos != -1) this.queue.splice(pos, 1);

     this.push(element, priority);
  }

   async _run(){
     while(this.queue.length)
        await this.task(this.queue.shift().element);
  }
}

注意:如果任务不是异步的,则应使用setTimeout(next, 0)之类的东西来允许进程消息中断它...

Note: If the task is not asynchronous you should use sth like setTimeout(next, 0) to allow the process messaging to interrupt it...

示例实现可以是图像加载器:

A sample implementation could be an image loader:

 class ImageLoader extends AsyncPriorityQueue  {
   constructor(){
     super(function task(url){
       const img = new Image();
       img.src = url;
       return new Promise(res => img.onload = res);
     });
   }
}

const loader = new ImageLoader;

 loader.push("a.jpg");
 loader.push("b.jpg", 1); // a bit more important
 // Oh, wait:
 loader.prioritize("a.jpg");

这篇关于javascript上的抢先式后台工作调度的一般解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆