![](/img/trans.png)
[英]How can I import dynamically generated code into webworker to be accessible in debugger
[英]Can I build a WebWorker that executes arbitrary Javascript code?
我想在WebWorker API上構建一個抽象層,允許 (1) 在 webworker 上執行任意函數,以及 (2) 將交互包裝在 Promise 中。 在高層次上,這看起來像這樣:
function bake() {
... // expensive calculation
return 'mmmm, pizza'
}
async function handlePizzaButtonClick() {
const pizza = await workIt(bake)
eat(pizza)
}
(顯然,可以毫不費力地添加帶有參數的方法。)
我的第一次workIt
是這樣的:
async function workIt<T>(f: () => T): Promise<T> {
const worker: Worker = new Worker('./unicorn.js') // no such worker, yet
worker.postMessage(f)
return new Promise<T>((resolve, reject) => {
worker.onmessage = ({data}: MessageEvent) => resolve(data)
worker.onerror = ({error}: ErrorEvent) => reject(error)
})
}
這失敗了,因為函數不是結構化可克隆的,因此不能在工作消息中傳遞。 (Promise 包裝器部分工作正常。)
序列化 Javascript 函數有多種選擇,有些比其他的更可怕。 但在我走那條路之前,我在這里錯過了什么嗎? 是否有另一種方法可以利用 WebWorker(或在單獨線程中執行的任何東西)來運行任意 Javascript?
除了我的評論之外,我認為一個示例會很有用,所以這里有一個基本的(沒有錯誤處理等)、自包含的示例,它從對象 URL加載工作人員:
Meta:我沒有將它發布在可運行的代碼片段視圖中,因為渲染的 iframe 在不同的來源運行(在我寫這個答案時
https://stacksnippets.net
- 請參閱片段輸出),這會阻止成功:在 Chrome ,我收到錯誤消息Refused to cross-origin redirects of the top-level worker script.
.無論如何,您可以復制文本內容,將其粘貼到此頁面上的開發工具 JS 控制台中,然后執行它以查看它是否有效。 而且,當然,它可以在同源上下文中的普通模塊中工作。
console.log(new URL(window.location.href).origin);
// Example candidate function:
// - pure
// - uses only syntax which is legal in worker module scope
async function get100LesserRandoms () {
// If `getRandomAsync` were defined outside the function,
// then this function would no longer be pure (it would be a closure)
// and `getRandomAsync` would need to be a function accessible from
// the scope of the `message` event handler within the worker
// else a `ReferenceError` would be thrown upon invocation
const getRandomAsync = () => Promise.resolve(Math.random());
const result = [];
while (result.length < 100) {
const n = await getRandomAsync();
if (n < 0.5) result.push(n);
}
return result;
}
const workerModuleText =
`self.addEventListener('message', async ({data: {id, fn}}) => self.postMessage({id, value: await eval(\`(\${fn})\`)()}));`;
const workerModuleSpecifier = URL.createObjectURL(
new Blob([workerModuleText], {type: 'text/javascript'}),
);
const worker = new Worker(workerModuleSpecifier, {type: 'module'});
worker.addEventListener('message', ({data: {id, value}}) => {
worker.dispatchEvent(new CustomEvent(id, {detail: value}));
});
function notOnMyThread (fn) {
return new Promise(resolve => {
const id = window.crypto.randomUUID();
worker.addEventListener(id, ({detail}) => resolve(detail), {once: true});
worker.postMessage({id, fn: fn.toString()});
});
}
async function main () {
const lesserRandoms = await notOnMyThread(get100LesserRandoms);
console.log(lesserRandoms);
}
main();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.