{"id":15893825,"url":"https://github.com/chinanf-boy/pseudo-worker-explain","last_synced_at":"2026-01-15T22:27:20.243Z","repository":{"id":90548486,"uuid":"119487019","full_name":"chinanf-boy/pseudo-worker-explain","owner":"chinanf-boy","description":"explain pseudo-worker Web worker polyfill ","archived":false,"fork":false,"pushed_at":"2018-02-01T14:00:57.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-08T08:47:13.524Z","etag":null,"topics":["explain","polyfill","web-worker","worker"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chinanf-boy.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-30T05:27:22.000Z","updated_at":"2018-02-01T13:59:26.000Z","dependencies_parsed_at":"2023-07-19T02:02:18.176Z","dependency_job_id":null,"html_url":"https://github.com/chinanf-boy/pseudo-worker-explain","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fpseudo-worker-explain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fpseudo-worker-explain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fpseudo-worker-explain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fpseudo-worker-explain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chinanf-boy","download_url":"https://codeload.github.com/chinanf-boy/pseudo-worker-explain/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246866100,"owners_count":20846496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["explain","polyfill","web-worker","worker"],"created_at":"2024-10-06T08:13:50.400Z","updated_at":"2026-01-15T22:27:20.195Z","avatar_url":"https://github.com/chinanf-boy.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# pseudo-worker\n\n浏览器-web-worker-polyfill\n\n[![explain](http://llever.com/explain.svg)](https://github.com/chinanf-boy/Source-Explain)\n    \nExplanation\n\n\u003e \"version\": \"1.0.0\"\n\n[github source](https://github.com/nolanlawson/pseudo-worker)\n\n~~[english](./README.en.md)~~\n\n---\n\n- [出发前准备](#确定主文件)\n\n---\n\n1. [定义局部变量](#定义局部变量)\n\n2. [定义-生命周期-钩子](#生命周期-钩子)\n\n- [executeEach](#executeEach)\n\n- [callErrorListener](#callErrorListener)\n\n- [addEventListener](#addEventListener)\n\n- [removeEventListener](#removeEventListener)\n\n- [postError](#postError)\n\n- [runPostMessage](#runPostMessage)\n\n- [postMessage](#postMessage)\n\n- [terminate](#terminate)\n\n- [workerPostMessage](#workerPostMessage)\n\n- [workerAddEventListener](#workerAddEventListener)\n\n3. [主逻辑 - 开启 - 最好从这里开始](#主逻辑)\n\n4. [有关-web-worker的资料](https://developer.mozilla.org/zh-CN/docs/Web/API/Worker/Worker)\n\n---\n\n- ~~polyfill.js~~\n\n---\n\n说明一下，两个关键点\n\n1. `Myworker` \n\n本项目 `pseudo.worker`, 作为 `Worker` 的 polyfill\n\n\u003e Myworker = new Worker(`worker.js`) // Worker == pseudo-worker\n\n2. `worker.js`\n\n这就是-**Worker-Api**-引入的, 脚本文件\n\n[可以看看有关-web-worker的资料](https://developer.mozilla.org/zh-CN/docs/Web/API/Worker/Worker)\n\n---\n\n## 确定主文件\n\npackage.json\n\n``` json\n\"main\": \"index.js\",\n```\n\n## index\n\n如果-你是一开始看-[请点击从定义变量开始](#定义局部变量)\n\n### doEval\n\n代码 1-9\n\n``` js\n'use strict';\n\nfunction doEval(self, __pseudoworker_script) {\n  /* jshint unused:false */\n  (function () {\n    /* jshint evil:true */\n    eval(__pseudoworker_script);\n  }).call(global);\n}\n\n```\n\n\u003e 运行-`worker.js`中脚本\n\n请注意，主线程中必须以`myWorker.onmessage`方式调用,  反之`worker.js` 脚本中, 只需定义 onmessage, 因为worker.js全域有效(`DedicatedWorkerGlobalScope`).\n\n该 `DedicatedWorkerGlobalScope` 对象(也就是 Worker 全局作用域)可以通过 `self` 关键字来访问.\n\n这也就是说\n\n``` js\n        workerSelf = {\n          postMessage: workerPostMessage,\n          addEventListener: workerAddEventListener,\n        };\n        // doEval(workerSelf,\n        // 变 workerSelf == self\n        // function doEval(self, \n```\n\n### pseudo-Worker\n\n#### 定义局部变量\n\n代码 11-21\n\n``` js\nfunction PseudoWorker(path) {\n  var messageListeners = [];\n  var errorListeners = [];\n  var workerMessageListeners = [];\n  var workerErrorListeners = [];\n  var postMessageListeners = [];\n  var terminated = false;\n  var script;\n  var workerSelf;\n\n  var api = this;\n\n\n```\n\n#### 生命周期-钩子\n\n这部分都是函数定义，可选择[下一小段「主逻辑」](#主逻辑)\n\n代码 23-136\n\n#### executeEach\n\n``` js\n  // custom each loop is for IE8 support\n  function executeEach(arr, fun) {\n    var i = -1;\n    while (++i \u003c arr.length) {\n      if (arr[i]) {\n        fun(arr[i]);\n      }\n    }\n  }\n\n```\n\n对`arr`每个值，运行`fun(arr[i])`\n\n---\n\n#### callErrorListener\n\n``` js\n  function callErrorListener(err) {\n    return function (listener) {\n      listener({\n        type: 'error',\n        error: err,\n        message: err.message\n      });\n    };\n  }\n\n``` \n\n更换-`err`-数据结构\n\n---\n\n#### addEventListener\n\n作为 `Myworker.addEventListener`\n\n``` js\n  function addEventListener(type, fun) {\n    /* istanbul ignore else */\n    if (type === 'message') {\n      messageListeners.push(fun);\n    } else if (type === 'error') {\n      errorListeners.push(fun);\n    }\n  }\n\n```\n\n``` js\nMyworker = new Worker()\n```\n\n- `messageListeners` message信息-触发函数-\u003e存储\n\n- `errorListeners` err信息-触发函数-\u003e存储\n\n---\n\n#### removeEventListener\n\n作为 `Myworker.removeEventListener`\n\n``` js\n  function removeEventListener(type, fun) {\n      var listeners;\n      /* istanbul ignore else */\n      if (type === 'message') {\n        listeners = messageListeners;\n      } else if (type === 'error') {\n        listeners = errorListeners;\n      } else {\n        return;\n      }\n      var i = -1;\n      while (++i \u003c listeners.length) {\n        var listener = listeners[i];\n        if (listener === fun) {\n          delete listeners[i];\n          break;\n        }\n      }\n  }\n```\n\n``` js\nMyworker = new Worker()\n```\n\n- listeners\n\n对`type` = 'message'|'error'\n\n然后遍历 `while listeners`\n\n删除相等的函数 `if (listener === fun) {`\n\n---\n\n#### postError\n\n规范错误输出, 并执行 `Myworker.onerror` 触发函数\n\n``` js\n  function postError(err) {\n    var callFun = callErrorListener(err);\n    if (typeof api.onerror === 'function') {\n      callFun(api.onerror);\n    }\n    if (workerSelf \u0026\u0026 typeof workerSelf.onerror === 'function') {\n      callFun(workerSelf.onerror);\n    }\n    executeEach(errorListeners, callFun);\n    executeEach(workerErrorListeners, callFun);\n  }\n```\n\n- [callErrorListener 改变数据存储结构-返回函数](#callerrorlistener)\n\n- [executeEach-遍历第一个变量 arr, 运行第二个变量fun(arr[i])](#executeeach)\n\n---\n\n#### runPostMessage\n\n传输-在`worker.js`-onmessage-\u003epostMessage(`msg`) 的 信息\n\n``` js\n function runPostMessage(msg) {\n    function callFun(listener) {\n      try {\n        listener({data: msg});\n      } catch (err) {\n        postError(err); \n      }\n    }\n\n    if (workerSelf \u0026\u0026 typeof workerSelf.onmessage === 'function') {\n      callFun(workerSelf.onmessage);\n    }\n    executeEach(workerMessageListeners, callFun);\n  }\n\n```\n\n- [postError 触发Myworker.onerror](#posterror)\n\n- [executeEach-遍历第一个变量 arr, 运行第二个变量fun(arr[i])](#executeeach)\n\n---\n\n#### postMessage\n\nMyworker.postMessage 的 api\n\n``` js\n  function postMessage(msg) {\n    if (typeof msg === 'undefined') {\n      throw new Error('postMessage() requires an argument');\n    }\n    if (terminated) { // 如果-停\n      return;\n    }\n    if (!script) { // 并没有脚本\n      postMessageListeners.push(msg); // 存储一下信息\n      return;\n    }\n    runPostMessage(msg);\n  }\n\n```\n\n``` js\nMyworker = new Worker()\n```\n\n\u003e 作为 `Myworker.postMessage`\n\n- runPostMessage\n\n---\n\n#### terminate\n\n设置-传输停止\n\n``` js\n  function terminate() {\n    terminated = true;\n  }\n```\n\n``` js\nMyworker = new Worker()\n```\n\n\u003e 作为 `Myworker.terminate`\n\n---\n\n#### workerPostMessage\n\n作为 `worker.js 中的 postMessage`\n\n``` js\n// worker.js\nonmessage = function(e) {\n  console.log('Message received from main script');\n  var workerResult = 'Result: ' + (e.data[0] * e.data[1]);\n  console.log('Posting message back to main script');\n  postMessage(workerResult); // \u003c---\n  // 输出信息给 worker.onmessage\n}\n```\n\n``` js\n  function workerPostMessage(msg) {\n    function callFun(listener) {\n      listener({\n        data: msg\n      });\n    }\n    if (typeof api.onmessage === 'function') {\n      // Myworker = new Worker(path)\n      // Myworker.onmessage 有所定义\n      callFun(api.onmessage); // 传输到外面\n    }\n    executeEach(messageListeners, callFun);\n  }\n```\n\n我们结合- 本节`worker.js` 例子说明一下，\n\n- [`executeEach(messageListeners, callFun);`](#executeeach)\n\n\n---\n\n#### workerAddEventListener\n\n作为 `worker.js 中的 addEventListener`\n\n``` js\n  function workerAddEventListener(type, fun) {\n    /* istanbul ignore else */\n    if (type === 'message') {\n      workerMessageListeners.push(fun);\n    } else if (type === 'error') {\n      workerErrorListeners.push(fun);\n    }\n  }\n```\n\n\n---\n\n#### 主逻辑\n\n代码 138-171\n\n``` js\n  var xhr = new XMLHttpRequest();  // 准备 ajax\n\n  xhr.open('GET', path); // path == worker.js\n  xhr.onreadystatechange = function () {\n    if (xhr.readyState === 4) {\n      if (xhr.status \u003e= 200 \u0026\u0026 xhr.status \u003c 400) {\n        script = xhr.responseText; // worker.js 内容\n        workerSelf = {\n          postMessage: workerPostMessage,\n          addEventListener: workerAddEventListener,\n        };\n        doEval(workerSelf, script);  // --- 1\n        var currentListeners = postMessageListeners; // 一开始是 []\n        postMessageListeners = [];\n        for (var i = 0; i \u003c currentListeners.length; i++) {\n          runPostMessage(currentListeners[i]); // --- 2\n        }\n      } else {\n        postError(new Error('cannot find script ' + path));\n      }\n    }\n  };\n\n  xhr.send(); // 开启\n\n  api.postMessage = postMessage; \n  // worker.postMessage\n  api.addEventListener = addEventListener; \n  // worker.addEventListener\n  api.removeEventListener = removeEventListener;\n  // worker.removeEventListener\n  api.terminate = terminate;\n  // worker.terminate\n\n  return api;\n}\n\nmodule.exports = PseudoWorker;\n```\n\n---\n\n在这里，我们再理清一下`worker`的信息传输顺序\n\n\u003e Myworker = new Worker(path)\n\n- 从`Myworker.postMessage(message)`\n\n- message - e.data -\u003e `worker.js` 中 `onmessage(e)`\n\n- `worker.js`- `onmessage(e)` 中 `postMessage(msg)` -\u003e\n\n- 传输-msg-到 e.data -\u003e `Myworker.onmessage(e)`\n\n---\n\n1. [`doEval(workerSelf, script); 请先看这个 \u003e\u003e`](#doeval)\n\n在`xhr.send();` - 我们对·path·的获取 - 触发`onreadystatechange` 函数 - 运行`doEval 函数`\n\n2. `workerPostMessage` 赋予 `worker.js` - postMessage\n\n\u003e [workerPostMessage ](#workerpostmessage)\n\n3. `workerAddEventListener` 赋予 `worker.js` - addEventListener\n\n\u003e [workerAddEventListener](#workeraddeventlistener)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinanf-boy%2Fpseudo-worker-explain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchinanf-boy%2Fpseudo-worker-explain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinanf-boy%2Fpseudo-worker-explain/lists"}