I'm writing a service for my angular 2 app using TypeScript. The service makes use of chrome's ServiceWorker
to listen for push notifications (see tutorial). The code (javascript) makes use of navigator
first to see if serviceWorker
is supported, then continues to complete registration etc., i.e.,
if ('serviceWorker' in navigator) {
console.log('Service Worker is supported');
navigator.serviceWorker.register('sw.js').then(function() {
return navigator.serviceWorker.ready;
}).then(function(reg) {
console.log('Service Worker is ready :^)', reg);
// TODO
}).catch(function(error) {
console.log('Service Worker error :^(', error);
});
}
I'd like to implemenet the above using TypeScript. However, the current lib.d.ts
used by the TypeScript compiler (see below) appears to have no definitions defined on Navigator
for the serviceWorker
or its associated methods such as serviceWorker.register
(I guess since it's a chrome-specific implementation).
interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver, NavigatorUserMedia {
readonly appCodeName: string;
readonly cookieEnabled: boolean;
readonly language: string;
readonly maxTouchPoints: number;
readonly mimeTypes: MimeTypeArray;
readonly msManipulationViewsEnabled: boolean;
readonly msMaxTouchPoints: number;
readonly msPointerEnabled: boolean;
readonly plugins: PluginArray;
readonly pointerEnabled: boolean;
readonly webdriver: boolean;
getGamepads(): Gamepad[];
javaEnabled(): boolean;
msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;
requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: MediaKeySystemConfiguration[]): PromiseLike<MediaKeySystemAccess>;
vibrate(pattern: number | number[]): boolean;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
The result is that I'm faced with compilation errors since the compiler can't find the associated serviceWorker
types. Given I'm new to JavaScript and TypeScript, I'm trying to determine the best way to proceed. I understand the options to be:
serviceWorker
defined and include that during compilation.lib.d.ts
Sage advice on the best option greatly appreciated.
Update
Attempted to cast to any to remove compilation errors, i.e.,
var nav = <any> navigator;
if ('serviceWorker' in nav) {
nav.serviceWorker.register('sw.js')
.then(function(reg) {
console.log('yey!', <any> reg);
}).catch(function(err) {
console.log('boo!', <any> err);
});
but now facing new errors, i.e.,
error TS7006: Parameter 'reg' implicitly has an 'any' type.
error TS7006: Parameter 'error' implicitly has an 'any' type.
Also, tempted to write definitions for the ServiceWorker using these details. However never done it before, so will need some practice!
In this example, TypeScript is used to create a service worker with a network first then cache, caching strategy, to support viewing previously visited pages when offline. When there is no network connection available and a previous page version is not cached, the service worker will display an offline page.
Service workers are specialized JavaScript assets that act as proxies between web browsers and web servers. They aim to improve reliability by providing offline access, as well as boost page performance.
A service worker is a event-driven JavaScript program that runs in a worker thread separate from a document. Once registered, a service worker is installed on the browser and persists indefinitely until evicted or deleted manually (see Eviction below).
Web workers and service workers are two types of workers available to websites. They have some things in common: Both run in a secondary thread, allowing JavaScript code to execute without blocking the main thread and the user interface.
ServiceWorker is not a chrome specific extension.
OP should refer to Jake Archibald's isSERVICEWORKERready? page for a rundown of the current state of ServiceWorker in the popular browsers.
I added the type definitions in tsd.d.ts
based on the interface information linked by OP and they seem to be working.
Please note that I referenced IPromise
interface from angular.d.ts.
Defined in tsd.d.ts
/// <reference path="angularjs/angular.d.ts" />
interface Navigator {
serviceWorker: ServiceWorkerContainer;
}
interface ServiceWorkerContainer {
register(scriptUrl: string, options?: RegistrationOptions): angular.IPromise<ServiceWorkerRegistration>;
}
interface RegistrationOptions {
scope: string;
}
interface ServiceWorkerRegistration {
installing?: ServiceWorker;
waiting?: ServiceWorker;
active?: ServiceWorker;
scope: string;
update(): angular.IPromise<void>;
unregister(): angular.IPromise<boolean>;
}
interface ServiceWorker {
scriptUrl: string;
state: string;
postMessage(message: any, transfer: Array<any>): void;
}
Referred in home-controller.ts
///<reference path='../../typings/tsd.d.ts' />
...
// dependencies are injected via AngularJS $injector
constructor() {
var vm = this;
vm.ctrlName = 'HomeCtrl';
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', { scope: '/' }).then(function(reg) {
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
} else {
console.warn('serviceWorker not available in navigator.');
}
}
Building and loading the app in the chrome
logs the following console message:
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With