【问题标题】:Using Webworkers in angular app (service worker cache access of data in angular-cli)在 Angular 应用程序中使用 Webworkers(服务工作者缓存访问 angular-cli 中的数据)
【发布时间】:2018-05-11 23:11:49
【问题描述】:

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

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 应用程序只创建一个工作人员并且没有内存问题。这将是表单提交的用户按钮操作的触发器。

我的问题:

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

其次,如果不可能,我可以从 Web Worker 访问 Service Worker 的缓存吗?是否可以访问此服务工作者缓存。这应该怎么做?欢迎任何帮助。

请注意,我能够与服务工作者一起工作,并且能够使用角度服务工作者缓存所有静态资产。

更新:

我能够使用我目前正在处理的以下配置获得在 Angular 应用程序中启用数据缓存的一些基本概念。

{
    "name": "someapi",
    "urls": ["/someuri", "/users"],
    "cacheConfig": {
      "strategy": "freshness",
      "maxSize": 20,
      "maxAge": "1h",
      "timeout": "5s"
    }
  }

更新:

我能够以粗略的方式启动并运行它,但它确实有效。将需要 XHR 请求的资产添加到资产部分的 ngsw-config.json 中。这将请求缓存到服务工作者缓存中。可以使用caches.open('ngsw:db:${name}') 打开服务工作者缓存,但我不必这样做。

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.

我是这样实现的。我为服务人员创建了一个角度服务:

@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 文件:

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 部分:

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

从组件,例如 app.component.ts 我触发了一个 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,但事实并非如此。服务工作者自动从缓存中提供文件(这太棒了)。但是,如果需要访问缓存,我​​发现可以在这里使用缓存 API 来完成:https://developer.mozilla.org/en-US/docs/Web/API/Cache

我确信事情可以根据最佳实践得到改进,并且文件结构可以变得更清晰。如果您找到更好的解决方案,请留下答案,以便对大家有所帮助。

【问题讨论】:

    标签: javascript angular angular-cli service-worker web-worker


    【解决方案1】:

    是的,这可以由服务人员完成,但是:

    • 如果浏览器认为 Service Worker 已经完成工作,它可以终止该 Service Worker。因此,请务必将所有内容包装在一个 Promise 中并使用 event.waitUntil 来确保进程在完成之前不会终止。

      self.addEventListener("消息", function(event) { 事件.waitUntil(测试(事件)); });

    • Service Worker 在单线程上运行,因此如果您执行长时间同步操作,您会减慢页面的每个请求。 Service Worker 不适合做长时间的计算。

    是的,共享工作者可以访问缓存 api。您可以使用全局变量缓存以与从服务工作者相同的方式访问它

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

    【讨论】:

    • 好的,这正是我需要的。对于第一点,考虑到未来的离线 XHR 请求将由 Service Worker 提供服务,它是否会终止/休眠?我在这里有点困惑。 event.waitUntil 定义在服务人员中?我如何以及在哪里定义它 - 在服务工作者(以及哪个文件,我没有在任何它的配置中看到服务工作者 ts/js 文件)或网络工作者?感谢第二个提示,不会执行长任务。为了避免服务工作者中的大任务,我可以从网络工作者访问caches.open(cacheName)。缓存是否可以在工作人员和选项卡之间共享?任何工作代码/参考?
    • 哎呀,第二个问题太恶心了。我看到缓存对窗口 api 是开放的。 Note that the Cache interface is exposed to windowed scopes as well as workersdeveloper.mozilla.org/en-US/docs/Web/API/Cache 。请忽略以上内容并使用以下内容作为问题。
    • 第一点,考虑到将来离线的 XHR 请求将由 Service Worker 提供服务,它是否会终止/休眠?我在这里有点困惑。 event.waitUntil 定义在服务人员中?我如何以及在哪里定义它 - 在服务工作者(以及哪个文件,我没有在任何它的配置中看到服务工作者 ts/js 文件)或网络工作者?比如说,我想访问缓存并需要 Web Worker 访问的 XHR 数据/静态资产?任何工作参考。我现在就试试这个。其次,如果我需要在 Ng 中添加来自 web workers 的 service worker 缓存,命名模式是什么?
    • 这是在服务上运行函数还是我们如何定义在服务中运行的外部函数? @angular/platform-webworker > ClientMessageBroker > runOnService
    • 服务工作者文件应该在构建过程之后构建。我在哪里访问这个 api,其次,如何从网络工作者那里访问?我正在使用 ng v5.2.0。刚看到这个。 stackoverflow.com/questions/42474908/…
    猜你喜欢
    • 2017-04-24
    • 2020-01-08
    • 1970-01-01
    • 2020-12-26
    • 2018-09-24
    • 1970-01-01
    • 2016-08-11
    • 2017-11-17
    • 2019-11-07
    相关资源
    最近更新 更多