From 7b667cfb9ff2700a9625db0f94fe6d31c217dee6 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Mon, 10 Dec 2018 22:46:04 +1300 Subject: [PATCH] Improve events (#454) * Fix typo in docs * Improve events Expose `error` event Add `once` Allow method chaining for `on` and `once` --- packages/api/src/Base.ts | 35 ++++++++++++++++++++++++--- packages/api/src/promise/index.ts | 12 ++++++--- packages/rpc-provider/src/types.ts | 2 +- packages/rpc-provider/src/ws/index.ts | 1 + packages/rpc-rx/src/types.ts | 3 ++- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/packages/api/src/Base.ts b/packages/api/src/Base.ts index d44a278f45..237cdbc038 100644 --- a/packages/api/src/Base.ts +++ b/packages/api/src/Base.ts @@ -169,14 +169,14 @@ export default abstract class ApiBase implements ApiBaseInterface * * ```javascript - * api.on('disconnected', () => { + * api.on('connected', () => { * console.log('API has been connected to the endpoint'); * }); * @@ -185,8 +185,33 @@ export default abstract class ApiBase implements ApiBaseInterface) => any): void { + on (type: ApiInterface$Events, handler: (...args: Array) => any): this { this._eventemitter.on(type, handler); + return this; + } + + /** + * @description Attach an one-time eventemitter handler to listen to a specific event + * + * @param type The type of event to listen to. Available events are `connected`, `disconnected`, `ready` and `error` + * @param handler The callback to be called when the event fires. Depending on the event type, it could fire with additional arguments. + * + * @example + *
+ * + * ```javascript + * api.once('connected', () => { + * console.log('API has been connected to the endpoint'); + * }); + * + * api.once('disconnected', () => { + * console.log('API has been disconnected from the endpoint'); + * }); + * ``` + */ + once (type: ApiInterface$Events, handler: (...args: Array) => any): this { + this._eventemitter.once(type, handler); + return this; } protected emit (type: ApiInterface$Events, ...args: Array): void { @@ -200,6 +225,10 @@ export default abstract class ApiBase implements ApiBaseInterface { + this.emit('error', error); + }); + this._rpcBase._provider.on('connected', async () => { this.emit('connected'); diff --git a/packages/api/src/promise/index.ts b/packages/api/src/promise/index.ts index 1ed01546bd..9b28b36832 100644 --- a/packages/api/src/promise/index.ts +++ b/packages/api/src/promise/index.ts @@ -154,10 +154,14 @@ export default class ApiPromise extends ApiBase - super.on('ready', () => - resolveReady(this) - ) + this._isReady = new Promise((resolveReady, rejectReady) => + super + .once('ready', () => + resolveReady(this) + ) + .once('error', () => + rejectReady(this) + ) ); } diff --git a/packages/rpc-provider/src/types.ts b/packages/rpc-provider/src/types.ts index aa442f6b8b..409fd058f0 100644 --- a/packages/rpc-provider/src/types.ts +++ b/packages/rpc-provider/src/types.ts @@ -37,7 +37,7 @@ export type JsonRpcResponse = JsonRpcObject & JsonRpcResponseBase; export type ProviderInterface$Callback = (result: any) => void; -export type ProviderInterface$Emitted = 'connected' | 'disconnected'; +export type ProviderInterface$Emitted = 'connected' | 'disconnected' | 'error'; export type ProviderInterface$EmitCb = (value?: any) => any; diff --git a/packages/rpc-provider/src/ws/index.ts b/packages/rpc-provider/src/ws/index.ts index 60ea41e9f1..36ac3c2f2d 100644 --- a/packages/rpc-provider/src/ws/index.ts +++ b/packages/rpc-provider/src/ws/index.ts @@ -245,6 +245,7 @@ export default class WsProvider implements WSProviderInterface { private onSocketError = (error: Event): void => { l.debug(() => ['socket error', error]); + this.emit('error', error); } private onSocketMessage = (message: MessageEvent): void => { diff --git a/packages/rpc-rx/src/types.ts b/packages/rpc-rx/src/types.ts index 2f3b3bbdc1..435e6922bb 100644 --- a/packages/rpc-rx/src/types.ts +++ b/packages/rpc-rx/src/types.ts @@ -3,6 +3,7 @@ // of the Apache-2.0 license. See the LICENSE file for details. import { ReplaySubject, Observable } from 'rxjs'; +import { ProviderInterface$Emitted } from '@polkadot/rpc-provider/types'; export type RpcRxInterface$Method = (...params: Array) => Observable | ReplaySubject; @@ -10,7 +11,7 @@ export type RpcRxInterface$Section = { [index: string]: RpcRxInterface$Method }; -export type RpcRxInterface$Events = 'connected' | 'disconnected'; +export type RpcRxInterface$Events = ProviderInterface$Emitted; export type RpcRxInterface = { readonly author: RpcRxInterface$Section;