在 angular 应用程序中使用 Webworkers(服务工作者缓存访问 angular-cli 中的数据) [英] Using Webworkers in angular app (service worker cache access of data in angular-cli)

查看:33
本文介绍了在 angular 应用程序中使用 Webworkers(服务工作者缓存访问 angular-cli 中的数据)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望使用工人运行一个函数(在后台).数据来自 http 请求.我正在使用模拟计算 (e.data[0] * e.data[1] * xhrData.arr[3])(由返回实际算法结果的函数替换)如下:

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);
};

这很好用.但是,这是一个纯 JS 实现.我打算为此使用一个服务(加上一个共享工作器),所以我每个 Angular 应用程序只创建一个工作器并且没有内存问题.这将是表单提交的用户按钮操作的触发器.

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.

我的问题:

首先,我想知道这是否可以由 Angular 本身的服务工作者完成,因为它也是一种后台工作者线程.

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.

第二,如果不可能,那么我可以从 Web Worker 访问 Service Worker 的缓存吗?以及是否可以访问此 Service Worker 缓存.这应该怎么做?欢迎任何帮助.

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.

请注意,我可以使用 Service Worker,并且可以使用 Angular Service Worker 缓存所有静态资产.

Note that I am able to work with service workers and I am able to cache all static assets using angular service workers.

我能够使用我目前正在处理的以下配置获得在 angular 应用程序中启用数据缓存的一些基本想法.

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"
    }
  }

更新:

我能够在粗略的情况下启动并运行它,但它起作用了.将需要 XHR 请求的资产添加到资产部分的 ngsw-config.json 中.这将请求缓存到 Service Worker 缓存中.可以使用 caches.open('ngsw:db:${name}') 打开 Service Worker 缓存,但我不必这样做.

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.

这是我如何实现的.我为服务工作者创建了一个 angular 服务:

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);
      }
  }

}

然后我在assets文件夹中创建了一个web-worker.js文件:

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);
};

我的 ngsw-config.json 有缓存 assets/test.md 的 assets 部分:

My ngsw-config.json had assets section which cached assets/test.md:

{
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  }

从组件,比如说 app.component.ts 我触发了一个 postMessage()

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');
  }

}

这使得 web-worker.js 触发 XHR 请求.虽然我原以为我将不得不自己使用缓存访问 api,但事实并非如此.Service Worker 自动从缓存中提供文件(这太棒了).但是,如果需要访问缓存,我​​发现可以使用此处的缓存 API 来完成:https://developer.mozilla.org/en-US/docs/Web/API/Cache

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.

推荐答案

是的,这可以由 Service Worker 完成,但是:

Yes this can be done by a service worker but :

  • 如果浏览器认为 Service Worker 已经完成工作,它可以终止 Service Worker.所以一定要把所有的东西都包装在一个 promise 中,并使用 event.waitUntil 来确保进程在完成之前不会被终止.

  • The browser can terminate a service worker if it thinks the service worker has finished working. So be sure to wrap everything inside a promise and use event.waitUntil to make sure that the process isn't terminated before it has finished.

self.addEventListener("message", function(event) {event.waitUntil(test(event));});

self.addEventListener("message", function(event) { event.waitUntil(test(event)); });

Service Worker 在单个线程上运行,因此如果您执行长时间的同步操作,您的页面的每个请求都会变慢.Service Worker 并不打算进行长时间的计算.

The service worker runs on a single thread, so if you do long synchronous operation you'd be slowing every request of your page. Service workers are not meant to do long calculation.

是的,共享 worker 可以访问缓存 api.您可以使用全局变量缓存以与从 Service Worker 相同的方式访问它

Yes shared workers can access the cache api. You can access it the same way you do from a service worker by using the global variable caches

caches.open(cacheName).then(function(cache) {
      cache.match("...")
});

这篇关于在 angular 应用程序中使用 Webworkers(服务工作者缓存访问 angular-cli 中的数据)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆