javascript上先发制人后台工作调度的一般解决方案

时间:2018-02-14 19:04:58

标签: javascript multithreading scheduling web-worker

以下是该方案: 当我的Web应用程序启动时,我想从本地存储中的几个表加载数据(使用indexedDB)。我将这项工作委托给网络工作者。它将依次加载每个表,并在加载每个表时触发包含数据的消息。在主线程上,侦听器将接收消息并将数据存储在缓存中。

但是,让我们说用户按下按钮来查看特定表格的数据。该应用程序调用一个检查缓存的函数,并发现该表的数据尚未加载。

此函数如何等待该表的数据被缓存,以便它可以返回数据?更重要的是,如果计划最后加载表怎么办?该函数如何向Web工作者发送消息以确定加载该特定表的优先级,以便尽快获得其数据?

这种先发制人的调度问题的清洁解决方案的一般模式是什么?我想尽可能避免民意调查。

1 个答案:

答案 0 :(得分:1)

Worker可以使用包含要加载的所有表的异步队列,并在特定优先级之后进行排序,因此您可以优先处理某些表,并将它们排序到表的前面。你没有展示出真正的实现,这是一个更通用的版本:

 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)这样的过程消息来中断它......

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

 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");