Использование веб-работников в Angular-приложении (сервисный работник кеширует доступ к данным в Angular-Cli) - PullRequest
0 голосов
/ 02 мая 2018

Я хочу запустить функцию (в фоновом режиме), используя рабочий. Данные поступают из 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, поскольку это также тип фонового рабочего потока.

Во-вторых, если это невозможно, могу ли я получить доступ к кешу сервисных работников из веб-работника? и возможно ли получить доступ к этому кешу рабочего сервиса. Как это должно быть сделано? Любая помощь приветствуется.

Обратите внимание, что я могу работать с сервисными работниками, и я могу кэшировать все статические активы, используя угловых сервисных работников.

Обновление:

Мне удалось получить некоторую базовую идею о включении кэширования данных в угловом приложении, используя следующую конфигурацию, над которой я сейчас работаю.

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

}

Затем я создал файл 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 был раздел активов, в котором кэшировались активы / test.md:

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

Я уверен, что все можно улучшить, а структурирование файлов можно сделать более чистым в соответствии с лучшими практиками. Если вы найдете лучшее решение, пожалуйста, оставьте ответ, чтобы он помог всем.

1 Ответ

0 голосов
/ 04 мая 2018

Да, это может сделать сервисный работник, но:

  • Браузер может прекратить работу сервисного работника, если он считает, что сервисный работник завершил работу. Поэтому обязательно заверните все в обещание и используйте event.waitUntil, чтобы убедиться, что процесс не завершен до его завершения.

    self.addEventListener ("message", function (event) { event.waitUntil (тест (событие)); });

  • Работник службы работает в одном потоке, поэтому, если вы выполняете длинную синхронную операцию, вы замедляете каждый запрос вашей страницы. Сервисные работники не предназначены для длинных расчетов.

Да, совместно используемые работники могут получить доступ к API кеша. Вы можете получить к нему доступ так же, как и от работника службы, используя глобальные переменные caches

caches.open(cacheName).then(function(cache) {
      cache.match("...")
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...