{"id":15893873,"url":"https://github.com/chinanf-boy/greenlet-explain","last_synced_at":"2026-01-17T18:38:22.635Z","repository":{"id":90548379,"uuid":"119183051","full_name":"chinanf-boy/greenlet-explain","owner":"chinanf-boy","description":"explain Move an async function into its own thread. 把异步函数移到worker","archived":false,"fork":false,"pushed_at":"2018-02-09T08:37:26.000Z","size":4,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T18:16:16.701Z","etag":null,"topics":["async","explain","greenlet","web-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":null,"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":null,"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-27T16:51:59.000Z","updated_at":"2021-03-22T11:40:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"d56a90fb-38df-4030-b874-01d3eaf843f8","html_url":"https://github.com/chinanf-boy/greenlet-explain","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chinanf-boy/greenlet-explain","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fgreenlet-explain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fgreenlet-explain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fgreenlet-explain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fgreenlet-explain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chinanf-boy","download_url":"https://codeload.github.com/chinanf-boy/greenlet-explain/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fgreenlet-explain/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28516195,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T18:28:00.501Z","status":"ssl_error","status_checked_at":"2026-01-17T18:28:00.150Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["async","explain","greenlet","web-worker"],"created_at":"2024-10-06T08:13:57.936Z","updated_at":"2026-01-17T18:38:22.605Z","avatar_url":"https://github.com/chinanf-boy.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# greenlet\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/developit/greenlet)\n\n~~[english](./README.en.md)~~\n\n---\n\n我们来说明一下，`worker`的信息传递顺序\n\n `1.myWorker.postMessage` -\u003e\n \n  `worker.js中,  2. onmessage`--\u003e \n \n `worker.js中, 3. postMessage` --\u003e \n \n `4. myWorker.onmessage`\n\n[onmessage- 更多](https://developer.mozilla.org/zh-CN/docs/Web/API/Worker/onmessage)\n\n``` js\n/** Move an async function into its own thread.\n *  @param {Function} fn\tThe (async) function to run in a Worker.\n */\nexport default function greenlet(fn) {\n\tlet w = new Worker(URL.createObjectURL(new Blob([\n            'onmessage='+( //     ------ 2\n                // 👌\n\t\t\t\tf =\u003e ({ data }) =\u003e Promise.resolve().then(\n\t\t\t\t\t() =\u003e f.apply(f, data[1]) // 带着从 -- 1，获得 a-输入变量\n\t\t\t\t).then(\n\t\t\t\t\td =\u003e { postMessage([data[0], null, d]); }, // --- 3\n\t\t\t\t\te =\u003e { postMessage([data[0], ''+e]); } //  --- 3\n\t\t\t\t)\n\t\t\t)+'('+fn+')' // 👌 把定义的函数放入 f，且运行返回-({ data }) 函数\n\t\t]))),\n\t\tc = 0, // 递增\n\t\tp = {}; \n\tw.onmessage = ({ data: [c,e,d] }) =\u003e { //  --- 4\n        p[c][e?1:0](e||d); \n        // 当-e-具有值时，说明具有错误\n        // e || d 都代表 f.apply(f, data[1])\n        // reject(e)\n\n        // 当 -e- 不具有值时说明\n        // 正常运行\n        // resolve(f.apply(f, data[1])\n\n\t\tdelete p[c]; // 作用完成\n\t};\n\treturn (...a) =\u003e new Promise( (y, n) =\u003e {\n\t\tp[++c] = [y, n]; // resolve reject\n\t\tw.postMessage([c, a]);  //      ---- 1\n\t});\n}\n```\n\n结合一下，示例\n\n``` js\nimport greenlet from 'greenlet'\n\nlet get = greenlet(async url =\u003e {\n\tlet res = await fetch(url)\n\treturn await res.json()\n})\n\nconsole.log(await get('/foo'))\n```\n\n先从定义开始 `fn`\n\n``` js\ngreenlet(fn) { \n    // fn == 「 async url =\u003e {\n    //       \tlet res = await fetch(url)\n    //       \treturn await res.json()\n    //         } 」\n\n// 其他不管先\n```\n\n`await get('/foo')` 使用\n\n``` js\n\treturn (...a) =\u003e new Promise( (y, n) =\u003e {\n        // a == '/foo'\n\t\tp[++c] = [y, n]; // resolve reject\n        w.postMessage([c, a]);  //   发送 c 递增顺序与 输入变量值\n        // 到 worker 定义的函数-onmesssage\n\t});\n```\n\n进入 `worker-onmessage`\n\n``` js\n\tlet w = new Worker(URL.createObjectURL(new Blob([\n            'onmessage='+( //     ------ 2\n                // 👌\n\t\t\t\tf =\u003e ({ data }) =\u003e Promise.resolve().then(\n\t\t\t\t\t() =\u003e f.apply(f, data[1]) // 带着从 -- 1，获得 a-输入变量\n\t\t\t\t).then(\n\t\t\t\t\td =\u003e { postMessage([data[0], null, d]); }, // --- 3\n\t\t\t\t\te =\u003e { postMessage([data[0], ''+e]); } //  --- 3\n\t\t\t\t)\n\t\t\t)+'('+fn+')' // 👌 把定义的函数放入 f，且运行返回-({ data }) 函数\n\t\t]))),\n```\n\n`('+fn+')` 我们先看看 这个括号\n\n`(f =\u003e //...)(fn)` 就是带入 `f` == `fn` 并运行\n\n``` js\n// 所以\n            'onmessage='+( //     ------ 2\n                // 👌\n\t\t\t\tf =\u003e ({ data }) =\u003e Promise.resolve().then(\n\t\t\t\t\t() =\u003e f.apply(f, data[1]) // 带着从 -- 1，获得 a-输入变量\n\t\t\t\t).then(\n\t\t\t\t\td =\u003e { postMessage([data[0], null, d]); }, // --- 3\n\t\t\t\t\te =\u003e { postMessage([data[0], ''+e]); } //  --- 3\n\t\t\t\t)\n            )+'('+fn+')'\n            \n// 变\n\n            'onmessage='({ data }) =\u003e Promise.resolve().then(\n\t\t\t\t\t() =\u003e f.apply(f, data[1]) // f == fn\n\t\t\t\t).then(\n\t\t\t\t\td =\u003e { postMessage([data[0], null, d]); },  // --- 3\n                    e =\u003e { postMessage([data[0], ''+e]); }  //  --- 3\n\t\t\t\t)\n\t\t\t)\n```\n\n下一步，来到 `--- 3`\n\n有两个-3，\n\n`d =\u003e` 和 `e =\u003e` 就像 `Promise(resolve,reject)` 只会运行一个\n\n- 默认正确\n\n\u003e 运行 `d =\u003e { postMessage([data[0], null, d]); }`\n\n- 错误❌\n\n\u003e 运行 `e =\u003e { postMessage([data[0], ''+e]); }`\n\n---\n\n不管运行哪个 `e||d` === `f.apply(f, data[1])`\n\n并来到 `w.onmessage`\n\n``` js\n// c 是递增顺序 , e 是 错误, d 是 默认\n\n// p的值来源于  p[++c] = [y, n];  \n// y == resolve\n// n == reject\n\n// p[c][1] == reject\n// p[c][0] == resolve\n\nw.onmessage = ({ data: [c,e,d] }) =\u003e { //  --- 4\n        p[c][e?1:0](e||d); \n\n        // e?1:0\n        // 如果-e-具有值时，说明具有错误\n        // e || d 都代表 f.apply(f, data[1])\n        // reject(e)\n\n        // 当 -e- 不具有值时说明\n        // 正常运行\n        // resolve(f.apply(f, data[1])\n\n\t\tdelete p[c]; // 作用完成, 删除\n\t};\n```\n\n因为 `y,n` 是来自`new Promise( (y, n) =\u003e`\n\n``` js\n\treturn (...a) =\u003e new Promise( (y, n) =\u003e {\n        // a == '/foo'\n\t\tp[++c] = [y, n]; // resolve reject\n        w.postMessage([c, a]);  //   发送 c 递增顺序与 输入变量值\n        // 到 worker 定义的函数-onmesssage\n\t});\n```\n\n`=\u003e` 绑定了 `this`, 所以 `p[c][e?1:0](e||d); `\n\n会返回-示例中结果\n\n``` js\nlet get = greenlet(async url =\u003e {\n\tlet res = await fetch(url)\n\treturn await res.json() // \u003c----\n})\n\nconsole.log(await get('/foo'))\n```\n\n像\n\n``` js\n\treturn (...a) =\u003e new Promise( (y, n) =\u003e {\n        y(async url =\u003e {\n\tlet res = await fetch(url)\n\treturn await res.json() \n        })\n        // or \n        // n(async url =\u003e {\n        // \tlet res = await fetch(url)\n        // \treturn await res.json() // \u003c----\n        // })\n\t});\n```\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinanf-boy%2Fgreenlet-explain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchinanf-boy%2Fgreenlet-explain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinanf-boy%2Fgreenlet-explain/lists"}