问题
I am trying to offload long running process that blocks my UI.
The WebWorker approach appears to be the best approach to this situation.
However, one of the libraries that I need to use has async/await.
The WebWorker has a limited JS API and does not appear to have async/await.
Is there a way to use Promises inside of a WebWorker?
Error
ReferenceError: __awaiter is not defined
Regards,
Daniel
Update:
Adding an __awaiter lead to the Promise not being recognised.
var __awaiter =
(this && this.__awaiter) ||
function(thisArg, _arguments, Promise, generator) {
return new Promise(function(resolve, reject) {
generator = generator.call(thisArg, _arguments);
function cast(value) {
return value instanceof Promise && value.constructor === Promise
? value
: new Promise(function(resolve) {
resolve(value);
});
}
function onfulfill(value) {
try {
step('next', value);
} catch (e) {
reject(e);
}
}
function onreject(value) {
try {
step('throw', value);
} catch (e) {
reject(e);
}
}
function step(verb, value) {
var result = generator[verb](value);
result.done
? resolve(result.value)
: cast(result.value).then(onfulfill, onreject);
}
step('next', void 0);
});
}
Here is the skeleton code for how the web worker is constructed.
/* eslint-disable */
export default function ModelWorker() {
this.window = this
onmessage = async (e) => {
console.log(e);
}
}
WorkerProxy.js
export default class WorkerProxy {
constructor(worker) {
const code = worker.toString()
const src = code.substring(code.indexOf('{') + 1, code.lastIndexOf('}'))
const blob = new Blob([src], { type: 'application/javascript' })
return new Worker(URL.createObjectURL(blob))
}
}
SomeComponent.js
import WorkerProxy from './WorkerProxy'
import ModelWorker from './ModelWorker'
if (!!window.Worker) {
const worker = new WorkerProxy(ModelWorker)
worker.addEventListener('message', e => console.log(e.data))
worker.postMessage({ message:message })
// Load labels, etc.
}
回答1:
async
/await
are part of ECMAScript language, and these are available in all global scopes, be it Window, Web Worker, Service Worker, Audio Worklet, Paint Worklet etc.
What these scopes may not have are some Web APIs, like the DOM API, MediaDevices API, Geolocation API and a few others. However, as long as the browser supports this ECMAScript feature, then all scopes will.
So I can't tell what is your problem, but it is definitely possible to use Promises and async/await in a Worker.
const worker = new Worker(
URL.createObjectURL(
new Blob([worker_script.textContent])
)
);
worker.onmessage = ({data}) => console.log(data);
<script type="worker-script" id="worker_script">
(async function() {
postMessage(['starting', performance.now()]);
await wait(2000);
postMessage(['ended', performance.now()]);
})();
function wait(time) {
return new Promise((res)=>setTimeout(res, time));
}
</script>
来源:https://stackoverflow.com/questions/55999143/javascript-webworker-async-await