Front-end black magic: webworker dynamic, JS file without having to create worker

Foreword

A few days ago, I and a discussion of this issue almost friends know, I felt this is very interesting, so write this article as a record
The article ideas and project code derived from the Friends of Scouting @ simon3000 , I have to be modified to meet the needs of a more understandable.
 
As used herein, the code has been authorized parties , see:
Thank you very much his understanding and encouragement
 

On the initial code address

 (Page into the project, under which the original-version directory is the author of the original code)

 


Webworker create problems brought about by JS file and path

Webworker, in fact, I have always felt that the use of relatively stiff, because it seems you need to create additional JS file to run, as follows
var worker =new Worker('work.js’)
 
This means that you need to create an additional js file. In this way it makes me feel a bit "old-fashioned." Because the ability to manipulate files JS poor, if you want to create the file, of course, there are methods, reference: https://github.com/eligrey/FileSaver.js/
 
But the question is, if you want to create the file, JS file creation often inseparable download! I was just trying to "quietly" to create a file, but the results JS suddenly pop up a download box when it is created, it can be unbearable. Ah, uncomfortable. (Here should be [difficult for me] expression package).
 
That is, this time webWorker is "static", is an extra-JS files, is constrained.
 

Four times the conversion, will become a regular function, which imposes WebWorker

But @ simon3000 recommendations let me shines! He told me that, based on his experience using webworker-loader (webpack technology stack) , there is a continuous conversion of a direct way to become a regular function WebWorker

 
This is a very exciting information.
 
Just look at his actions:
// 文件名为main.js
function work () {
  onmessage = ({data: {message}}) => {
    console.log ('i am worker, receive:' + message);
    postMessage ({result: 'message from worker'});
  };
}

const runWorker = f => {
  const worker = new Worker (
    URL.createObjectURL (new Blob ([`(${f.toString ()})()`]))
  );

  worker.onmessage = ({data: {result}}) => {
    console.log ('i am main thread, receive:' + result);
  };

  worker.postMessage ({message: 'message from main thread'});
};

const testWorker = runWorker (work);
这段代码是我在他的代码基础上简化的
 
输出结果:
 

用Promise和闭包的方式去改造

我们再让它更通用一些,用Promise和闭包的方式去改造它,把runworker函数改造成一个makeworker函数
// 文件名为index.js
function work () {
  onmessage = ({data: {jobId, message}}) => {
    console.log ('i am worker, receive:-----' + message);
    postMessage ({jobId, result: 'message from worker'});
  };
}

const makeWorker = f => {
  let pendingJobs = {};

  const worker = new Worker (
    URL.createObjectURL (new Blob ([`(${f.toString ()})()`]))
  );

  worker.onmessage = ({data: {result, jobId}}) => {
    // 调用resolve,改变Promise状态
    pendingJobs[jobId] (result);
    // 删掉,防止key冲突
    delete pendingJobs[jobId];
  };

  return (...message) =>
    new Promise (resolve => {
      const jobId = String (Math.random ());
      pendingJobs[jobId] = resolve;
      worker.postMessage ({jobId, message});
    });
};

const testWorker = makeWorker (work);

testWorker ('message from main thread').then (message => {
  console.log ('i am main thread, i receive:-----' + message);
});

 

输出结果
 

总结

这次探讨告诉我们什么道理呢?
  • 第一,function.toString得到的并不是一个没有意义的字符串,它是完全可以被用来运行的
  • 第二,通过这种方式,webworker不需要借助额外的JS文件了,webworker完全动态化和自由化,你可以在主线程中创建任意个webworker!
  • 第三,我通过这次的交谈了解到一个道理,编程除了考量逻辑思维,信息差也是考量的一大因素。我之前也想过用webworker做这些事情,可是我不知道能用这样的四重转换呀!我也不知道function.toString得到的字符串居然是有作用的。信息差,也是会造成差距的。所以工程上也经验和前瞻也同样重要。

其他参考资料

Guess you like

Origin www.cnblogs.com/penghuwan/p/11546407.html