ServiceWorker

时间:2016-07-03 17:20:02

标签: javascript typescript angular service-worker

我正在使用TypeScript为我的angular 2应用程序编写服务。该服务使用chrome的ServiceWorker来监听推送通知(请参阅tutorial)。代码(javascript)首先使用navigator来查看是否支持serviceWorker,然后继续完成注册等,即

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

我想使用TypeScript实现上述功能。但是,TypeScript编译器使用的当前lib.d.ts(见下文)似乎没有在Navigator上为serviceWorker或其相关方法(例如serviceWorker.register(I {I}}定义定义猜测,因为它是特定于铬的实现。)

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

结果是我遇到了编译错误,因为编译器找不到关联的serviceWorker类型。鉴于我是JavaScript和TypeScript的新手,我正在尝试确定最佳的继续方式。我理解选项:

  1. 保留js代码并简单地忽略编译错误(不是 理想)。
  2. 保留js代码并以某种方式抑制类型错误     汇编。
  3. 查找现有的打字稿定义库     已定义serviceWorker并在编译期间包含该内容。
  4. 为导航器或某种方式编写我自己的打字稿定义文件     扩展现有的lib.d.ts
  5. Sage对最佳选择的建议非常感谢。

    更新

    尝试强制转换为删除编译错误,即

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

    但现在面临新的错误,即

    error TS7006: Parameter 'reg' implicitly has an 'any' type.
    error TS7006: Parameter 'error' implicitly has an 'any' type.
    

    另外,很想使用这些details为ServiceWorker编写定义。但是从来没有做过,所以需要一些练习!

3 个答案:

答案 0 :(得分:2)

原始答案

以下是我创建的用于WebStorm的打字:CRD

然后在我的service-worker.ts文件中,我添加了一个引用:/// <reference path="YOUR_PATH_HERE/service-worker.d.ts" />

相应地调整你的路径,或者让它们成为全局路径,你应该设置得很漂亮。它相当完整,但我确定它缺少一些东西。无论如何,我希望这会有所帮助。

2018年更新:

我发布了这些定义的新版本,以及lib.webworker.d.ts以及任何es5 +库(lib.es5.d.ts,lib.es2015.d.ts等):{{3 }}。这个集合今天应该更加重要。

答案 1 :(得分:1)

您可以在TypeScript文件中添加界面,当lib.d.ts更新时,编译器会告诉您不再需要它。

interface Navigator {
    getUserMedia(
        options: { video?: bool; audio?: bool; }, 
        success: (stream: any) => void, 
        error?: (error: string) => void
        ) : void;
}

navigator.getUserMedia(
    {video: true, audio: true}, 
    function (stream) {  },
    function (error) {  }
);

您可以使用任意参数调用any对象,而不是更改定义,例如:

 var n = <any>navigator;
    n.getUserMedia  = n.getUserMedia || n.webkitGetUserMedia || n.mozGetUserMedia || n.msGetUserMedia;
    return  n.getUserMedia({video: true, audio:true}, onSuccess, onFail);

答案 2 :(得分:1)

ServiceWorker不是特定于Chrome的扩展程序。

OP应该参考Jake Archibald的isSERVICEWORKERready?页面,了解流行浏览器中ServiceWorker的当前状态。

我根据OP的界面信息linkedtsd.d.ts中添加了类型定义,它们似乎正在运行。

请注意我从angular.d.ts引用了IPromise界面。

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

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

在Chrome中构建和加载应用

enter image description here

记录以下控制台消息:

enter image description here

希望这有帮助。