简体   繁体   English

TypeScript ServiceWorker 的类型定义

[英]TypeScript type definitions for ServiceWorker

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 ).我正在使用 TypeScript 为我的 angular 2 应用程序编写服务。该服务使用 chrome 的ServiceWorker来侦听推送通知(请参阅教程)。 The code (javascript) makes use of navigator first to see if serviceWorker is supported, then continues to complete registration etc., ie,代码(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);
  });
}

I'd like to implem.net 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).我想使用 TypeScript 来实现上面的内容。但是,TypeScript 编译器(见下文)使用的当前lib.d.ts似乎没有在Navigator上为serviceWorker或其相关方法(如 serviceWorker)定义定义serviceWorker.register (我猜是因为它是特定于 chrome 的实现)。

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.结果是我遇到了编译错误,因为编译器找不到关联的serviceWorker类型。 Given I'm new to JavaScript and TypeScript, I'm trying to determine the best way to proceed.鉴于我是 JavaScript 和 TypeScript 的新手,我正在尝试确定继续进行的最佳方式。 I understand the options to be:我理解的选项是:

  1. Keep the js code and simply ignore the compilation errors (not ideal).保留 js 代码并简单地忽略编译错误(不理想)。
  2. Keep the js code and somehow suppress the type errors during compilation.保留 js 代码并以某种方式抑制编译期间的类型错误。
  3. Find an existing typescript definitions library that has serviceWorker defined and include that during compilation.查找已定义 serviceWorker 的现有serviceWorker定义库,并在编译期间包含它。
  4. Write my own typescript definition file for navigator or somehow extend the existing lib.d.ts为导航器编写我自己的 typescript 定义文件或以某种方式扩展现有的lib.d.ts

Sage advice on the best option greatly appreciated.非常感谢关于最佳选择的明智建议。

Update更新

Attempted to cast to any to remove compilation errors, ie,尝试转换为 any 以消除编译错误,即

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, ie,但现在面临新的错误,即

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 .此外,还试图使用这些详细信息为 ServiceWorker 编写定义。 However never done it before, so will need some practice!但是以前从未做过,所以需要一些练习!

Type definitions for ServiceWorker and friends are now available from DefinitelyTyped/service_worker_api : 现在可以从DefinitelyTyped / service_worker_api获得ServiceWorker和朋友的类型定义:

$ typings install dt~service_worker_api --global --save
service_worker_api
└── (No dependencies)

Usage example: 用法示例:

// data-access.service.ts
/// <reference path="typings/globals/service_worker_api/index.d.ts" />
import { Injectable } from '@angular/core';

@Injectable()
export class DataAccess {
    constructor() {
        navigator.serviceWorker.register('service-worker.js', { scope: '/api/' });
    }
}

Adjust the paths as necessary. 根据需要调整路径。

Original Answer 原始答案

Here are the Typings I created to use with WebStorm: Gist . 以下是我创建的与WebStorm一起使用的打字: Gist

Then in my service-worker.ts file I include a reference: /// <reference path="YOUR_PATH_HERE/service-worker.d.ts" /> . 然后在我的service-worker.ts文件中包含一个引用: /// <reference path="YOUR_PATH_HERE/service-worker.d.ts" />

Adjust your path accordingly, or make them global and you should be pretty set. 相应地调整您的路径,或使它们全局化,您应该设置得相当漂亮。 It's fairly complete, but I'm sure it's missing some things. 它相当完整,但我确定它缺少一些东西。 Anyway, I hope this helps. 无论如何,我希望这会有所帮助。

2018 Update: 2018年更新:

I published a new edition of these definitions to work with lib.webworker.d.ts along with any es5+ library (lib.es5.d.ts, lib.es2015.d.ts, etc) here: Service Worker Typings to Supplement lib.webworker.d.ts . 我发布了这些定义的新版本,以及lib.webworker.d.ts以及任何es5 +库(lib.es5.d.ts,lib.es2015.d.ts等): Service Worker Typings to Supplement lib .webworker.d.ts This set should be much more relevant today. 这个集合今天应该更加重要。

You can add to the interface in your TypeScript file and when the lib.d.ts is updated, the compiler will tell you that you no longer need it. 您可以在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) {  }
);

or 要么

Instead of changing the definition you can cast to an any object an call with arbitray parameters eg: 您可以使用arbitray参数调用any对象,而不是更改定义,例如:

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

ServiceWorker is not a chrome specific extension. ServiceWorker不是特定于chrome的扩展。

OP should refer to Jake Archibald's isSERVICEWORKERready? OP应该参考Jake Archibald的isSERVICEWORKERready? page for a rundown of the current state of ServiceWorker in the popular browsers. 有关流行浏览器中ServiceWorker当前状态的详细信息页面。

I added the type definitions in tsd.d.ts based on the interface information linked by OP and they seem to be working. 我根据OP 链接的接口信息在tsd.d.ts添加了类型定义,它们似乎正在工作。

Please note that I referenced IPromise interface from angular.d.ts . 请注意 ,我从angular.d.ts引用了IPromise接口。

Defined in tsd.d.ts 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 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 在chrome中构建和加载应用程序

在此输入图像描述

logs the following console message: 记录以下控制台消息:

在此输入图像描述

Hope this helps. 希望这可以帮助。

You can now use types for a service worker directly in javascript without installing additional packages:您现在可以直接在 javascript 中为 Service Worker 使用类型,而无需安装额外的包:

// @ts-check
/// <reference no-default-lib="true"/>
/// <reference lib="webworker" />
(
  /** @param worker {ServiceWorkerGlobalScope} */
  (worker) => {


    worker.addEventListener('install', (event) => {
      // ...
    });


})(/** @type {any} */(self) );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM