import { WorkerServiceProtocol } from "@here/harp-datasource-protocol" ; import { LoggerManager } from "@here/harp-utils" ; const logger = LoggerManager . instance . create ( "WorkerService" , { enabled : true } ) ; declare let self ; /**
 * Response for  WorkerService procession results.
  export interface WorkerServiceResponse { /**
     * Response object.
     */ response : any ; /**
     * Transfer list containing a list of `ArrayBuffer` which transfer ownership from web worker
     * to UI thread.
     */ transferList ? : ArrayBuffer [ ] ; } /**
 * Header information for a [[RequestMessage]].
 */ interface RequestEntry { /**
     * ID of service.
     */ service : string ; /**
     * Unique ID of message.
     */ messageId : number ; /**
     * Contains `true` if message has been processed, and response has been sent.
     */ responseSent : boolean ; } remarks export abstract class WorkerService { private readonly m_pendingRequests : Map < number , RequestEntry > = new Map ( ) ; param serviceId constructor ( readonly serviceId ) { self . addEventListener ( "message" , this . onMessage ) ; const isInitializedMessage = { service : serviceId , type : WorkerServiceProtocol . ServiceMessageName . Initialized } ; self . postMessage ( isInitializedMessage ) ; } /**
     * Destroy the `WorkerService`. Cancels all pending requests ad removes itself from the message
     * queue.
     */ destroy ( ) { this . cancelAllPendingRequests ( ) ; self . removeEventListener ( "message" , this . onMessage ) ; } param message protected handleMessage ( message ) { logger . error ( `[${ this . serviceId }]: Invalid message ${ message . type }` ) ; } param request protected handleRequest ( request ) { throw new Error ( `ServiceAdapter[${ this . serviceId }]: Invalid request '${ request . type }'` ) ; } param message private readonly onMessage = ( message ) => { if ( typeof message . data . service !== "string" || message . data . service !== this . serviceId ) { return ; } try { if ( WorkerServiceProtocol . isRequestMessage ( message . data ) ) { const request = message . data ; const requestEntry = { service : request . service , messageId : request . messageId , responseSent : false } ; this . m_pendingRequests . set ( request . messageId , requestEntry ) ; this . tryHandleRequest ( request . request ) . then ( response => { this . doSendResponse ( requestEntry , { service : this . serviceId , type : WorkerServiceProtocol . ServiceMessageName . Response , messageId : request . messageId , response : response . response } , response . transferList ) ; } ) . catch ( error => { this . doSendResponse ( requestEntry , { service : this . serviceId , type : WorkerServiceProtocol . ServiceMessageName . Response , messageId : request . messageId , errorMessage : error . toString ( ) , errorStack : error . stack } ) ; } ) ; } else { this . tryHandleMessage ( message . data ) ; } } catch ( err ) { logger . error ( `[${ this . serviceId }]: Unhandled exception when handling ${ message . type }` ) ; } } ; /**
     * Safety belt over `handleMessage` for correct exception handling & logging.
     */ private tryHandleMessage ( message ) { try { this . handleMessage ( message ) ; } catch ( error ) { logger . error ( `[${ this . serviceId }]: Failed, handling message ${ message . type }` ) ; } } /**
     * Safety belt over `handleRequest` for correct exception handling in promise chain.
     */ private tryHandleRequest ( request ) { try { return this . handleRequest ( request ) ; } catch ( error ) { logger . error ( `[${ this . serviceId }]: Failure` , error ) ; return Promise . reject ( error ) ; } } private doSendResponse ( requestEntry , response , transferList ? ) { if ( requestEntry . responseSent ) { return ; } if ( transferList !== undefined ) { self . postMessage ( response , transferList ) ; } else { self . postMessage ( response ) ; } requestEntry . responseSent = true ; this . m_pendingRequests . delete ( requestEntry . messageId ) ; } private cancelAllPendingRequests ( ) { this . m_pendingRequests . forEach ( requestEntry => { this . doSendResponse ( requestEntry , { service : this . serviceId , type : WorkerServiceProtocol . ServiceMessageName . Response , messageId : requestEntry . messageId , errorMessage : "cancelled" } ) ; } ) ; } }