I wish to run an function (in the background) using a worker. The data comes from a http request. I am using a mock calculation (e.data[0] * e.data[1] * xhrData.arr[3])
(replaced by a function returning the actual algo result) as below:
var ajax = function() {
var prom = new Promise(function(resolve, reject){
if (!!XMLHttpRequest) {
var xhttp = new XMLHttpRequest();
xhttp.onload = function () {
if (this.readyState == 4 && this.status == 200) {
resolve(JSON.parse(this.responseText));
}
};
// Cache Logic - Will be adding logic to check cache
// if test.json is in cache.
// If it is then fetch res from cache
// There will be multiple XHR requests in parallel, not one
xhttp.open("GET", "test.json", true);
xhttp.send();
}
});
return prom;
}
async function test (e) {
var workerResult, xhrData;
try {
xhrData = await ajax();
workerResult = (e.data[0] * e.data[1] * xhrData.arr[3]);
postMessage({res: workerResult});
} catch(err) {
postMessage({err: 'Failed'});
}
}
onmessage = function (e) {
test(e);
};
This works fine. But, this is a pure JS implementation. I was planning to use a service (plus a shared worker) for this so I create only one worker per angular app and dont have memory issues. This is going to be a trigger from a user button action of form submit.
My question:
First, I am wondering if this can be done by service workers in Angular itself since it is also a type of background worker thread.
Second, If not possible then can I access the cache of service workers from web worker? and Is it possible to access this service worker cache. How is this supposed to be done? Any help is welcome.
Note that I am able to work with service workers and I am able to cache all static assets using angular service workers.
Update:
I was able to get some basic idea of enabling data cache in the angular app using following config which I am currently working on.
{
"name": "someapi",
"urls": ["/someuri", "/users"],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 20,
"maxAge": "1h",
"timeout": "5s"
}
}
Update:
I was able to get this up and running in a crude but it worked. Added the asset that needed the XHR request into the ngsw-config.json in the assets section. This cached the request into service worker cache. The service workers cache can be opened using caches.open('ngsw:db:${name}')
but I did not have to do that.
I created a web worker file inside the assets folder
The XHR request was made in it.
When a XHR was made the service worker automatically picked up the cache
So I did not have to use any alternate methods of cache access.
Sworkers was automatically served the XHR request from the cache.
Here is how I achieved that. I created a service in angular for the service worker:
@Injectable({
providedIn: 'root'
})
export class WebworkerService {
myWorker: any;
constructor() {
this.myWorker = new Worker('/assets/web-worker.js');
this.myWorker.onmessage = function(data) {
console.log(data);
}
}
}
Then I created a web-worker.js
file in the assets folder:
var ajax = function() {
var prom = new Promise(function(resolve, reject){
if (!!XMLHttpRequest) {
var xhttp = new XMLHttpRequest();
xhttp.onload = function () {
if (this.readyState == 4 && this.status == 200) {
resolve(this.responseText);
}
};
xhttp.open("GET", "/assets/test.md", true);
xhttp.send();
}
});
return prom;
}
async function test (e) {
var workerResult, xhrData;
try {
xhrData = await ajax();
workerResult = xhrData; // Some calculation or activity here
postMessage({res: workerResult});
} catch(err) {
postMessage({err: 'Failed'});
}
}
onmessage = function (e) {
test(e);
};
My ngsw-config.json
had assets section which cached assets/test.md:
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**"
]
}
}
From the component, say for example, app.component.ts I triggered a postMessage()
@Component({
selector: 'app-root',
template:`
<h1 (click)="myHttp()">
Some Client Event
</h1>
`,
styleUrls: ['./app.component.css'],
providers: []
})
export class AppComponent {
constructor(private _ww: WebworkerService) { }
myHttp() {
this._ww.myWorker.postMessage('Test');
}
}
This makes the web-worker.js trigger the XHR request. Though I was expecting I will have to use a cache access api my self, it was not so. The service worker automatically served the file from the cache (Which is fantastic). However if there is a need to access the cache I found this can be done using the cache API here: https://developer.mozilla.org/en-US/docs/Web/API/Cache
I am sure things can be bettered and file structuring can be made cleaner as per best practices. If you find a better solution please leave an answer so it helps everyone.