@actyx-contrib/ng-pond 中文文档教程

发布于 4年前 浏览 9 更新于 3年前

ng-Pond

使用 Actyx Pond 框架集成为您的服务角度应用。 使用 ActyxPondService 扩展您的工具链以观察整个应用程序中的鱼并加快您的 UI 项目并在几个小时内编写分布式应用程序。

Installation

ng-pond 可作为 npm 包使用。

npm install @actyx-contrib/ng-pond

Quick start

ActyxPondService

ActyxPondService 作为单例实例添加到您的根模块,并保持池塘内部缓存的优势。

Example:

文件:app.module.ts

import { AppComponent } from './app.component';
import { ActyxPondService } from '@actyx-contrib/ng-pond'

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [ActyxPondService],
  bootstrap: [AppComponent]
})
export class AppModule {}

Use the pond api

在您的组件中使用简单的 pond api 作为回调或 rxjs observables。 这将使您有机会在代码中使用您的鱼状态或使用 async 管道来构建响应式和最先进的用户界面。

注意:强烈建议在关注点分离 (SoC) 中构建应用程序。 直接在组件中使用 PondService 会使维护项目和为组件编写 e2e 和单元测试变得更加困难。

Example:

Logic:

文件:app.component.ts

import { Component } from '@angular/core';
import { ActyxPondService } from '@actyx-contrib/ng-pond'
import { MachineFish, State } from '../fish/MachineFish';
import { Observable } from 'rxjs';
import { ConnectivityStatus } from '@actyx/pond';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  machine$: Observable<State>
  connectivity$: Observable<ConnectivityStatus>

  constructor(private pondService: ActyxPondService) {
    this.machine$ = this.pondService.observe$(MachineFish.of('Machine1'))
    this.connectivity$ = this.pondService.getNodeConnectivity$()
  }

  async start() {
    const pond = await this.pondService.getPond()
    MachineFish.emitProdStartedEvent(pond, 'Machine1', 'order1')
  }

  async stop() {
    const pond = await this.pondService.getPond()
    MachineFish.emitProdStoppedEvent(pond, 'Machine1', 'order1')
  }
}
Template:

文件:app.component.html

<h1>Angular - Actyx-Pond - Machine control</h1>
<div *ngIf="connectivity$ | async as connectivity">
  <h2>Connectivity: {{connectivity.status | json}}</h2>
</div>
<div *ngIf="machine$ | async as machine; else loading">
  <div>
    <h2>Machine {{machine.machineId}}</h2>
    <dl>
      <dt>state:</dt>
      <dd>{{machine.state}}</dd>
    </dl>
  </div>
  <button *ngIf="machine.state==='stopped'" (click)="start()">start</button>
  <button *ngIf="machine.state==='started'" (click)="stop()">stop</button>
</div>
<ng-template #loading>Loading machine data...</ng-template>
Fish

文件:MachineFish.ts

import { Fish, FishId, Pond, Tag } from '@actyx/pond'
export type State =
  | { state: 'idle', machineId: string }
  | { state: 'inProduction', machineId: string, orderId: string }
export type Event =
  | { eventType: 'prodStarted', machineId: string, orderId: string }
  | { eventType: 'prodStopped', machineId: string, orderId: string }

const machineTag = Tag<Event>('machine')

export const MachineFish = {
  tags: { machineTag },
  of: (machineId: string): Fish<State, Event> => ({
    fishId: FishId.of('machineFish', machineId, 0),
    initialState: { state: 'idle', machineId },
    where: machineTag.withId(machineId),
    onEvent: (state, event) => {
      switch (event.eventType) {
        case 'prodStarted':
          return {
            state: 'inProduction',
            machineId: state.machineId,
            orderId: event.orderId,
          }
        case 'prodStopped':
          return {
            state: 'idle',
            machineId: state.machineId,
          }
      }
      return state
    },
  }),
  emitProdStoppedEvent: (pond: Pond, machineId: string, orderId: string) =>
    pond.emit(
      machineTag.withId(machineId),
      { eventType: 'prodStopped', machineId, orderId }
    ),
  emitProdStartedEvent: (pond: Pond, machineId: string, orderId: string) =>
    pond.emit(
      machineTag.withId(machineId),
      { eventType: 'prodStarted', machineId, orderId }
    ),
}

Registry fish

池中有两种创建方式注册鱼。 observeAllobserve 注册表鱼并将实体鱼映射为第二步。 observeAll 非常有策略,下面是注​​册表鱼的示例。

Example:

注意:这个例子建立在上面的Use the pond api例子之上。

Logic:

文件:app.component.ts

// [..]
  allMachines$: Observable<ReadonlyArray<State>>

  constructor(private pondService: ActyxPondService) {
    this.machine$ = this.pondService.observe$(MachineFish.of('Machine1'))
    this.allMachine$ = this.pondService.observeRegistry$(MachineFish.registry(), s => s, MachineFish.of)
    this.connectivity$ = this.pondService.getNodeConnectivity$()
  }
// [..]
}
Template:

文件:app.component.html

<!-- [..] -->
<div *ngFor="let machine of (allMachines$ | async)">
  <dl>
    <dt>Name:</dt>
    <dd>{{machine.machineId}}</dd>
    <dt>State:</dt>
    <dd>{{machine.state}}</dd>
  </dl>
</div>
<!-- [..] -->
Fish

文件:MachineFish.ts

export const MachineFish = {
  // [..]
  registry: (): Fish<string[], Event> => ({
    fishId: FishId.of('machineRegFish', 'reg', 0),
    initialState: [],
    where: machineTag,
    onEvent: (state, event) => {
      if (!state.includes(event.machineId)) {
        state.push(event.machineId)
      }
      return state
    },
  }),
  // [..]

Service overview

查看关于 Actyx-Pond 的文档获取更多详细信息 https://developer.actyx.com/docs/pond/introduction/

您将在包的定义文件中找到详细的 api 文档。

TS/JS Promise interface:

  • getPond()
  • emit(tags, event)
  • observe(fish, onStateChanged)
  • observeRegistry(registryFish, mapToProperty, makeEntityFish, onStateChanged)
  • observeAll(seedEventsSelector, makeFish, opts, onStateChanged)
  • observeOne(seedEventSelector, makeFish, onStateChanged, stoppedByError)
  • getPondState(callback)
  • pondInfo()
  • run(fish, fn)
  • keepRunning(fish, fn, autoCancel)

RxJs integration:

注意并非每个函数都有 RxJs 包装器。 在这种情况下,请使用上面的那个。

  • getRxPond()
  • observeRegistry$(registryFish, mapToProperty, makeEntityFish)
  • observe$(fish)
  • observeAll$(seedEventsSelector, makeFish, opts)
  • observeOne$(seedEventsSelector, makeFish)
  • getPondState$()
  • getNodeConnectivity$()
  • waitForSwarmSync$()
  • run$(fish, fn)

ng-Pond

Use the Actyx Pond framework integrated as a service in your angular application. Expand your toolchain with the ActyxPondService to observe fish all over your application and speed up your UI projects and write distributed apps in a couple of hours.

???? Installation

ng-pond is available as a npm package.

npm install @actyx-contrib/ng-pond

???? Quick start

???? ActyxPondService

Add the ActyxPondService to your root module as singleton instance and keep the advantage of the pond's internal caching.

???? Example:

File: app.module.ts

import { AppComponent } from './app.component';
import { ActyxPondService } from '@actyx-contrib/ng-pond'

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [ActyxPondService],
  bootstrap: [AppComponent]
})
export class AppModule {}

???? Use the pond api

Use the simple pond api in your components as with callbacks or with rxjs observables. This will give you the opportunity to use your fish states in the code or use async pipelines to build reactive and state of the art user interfaces.

Note: It is highly recommended to build applications in separation of concerns (SoC). Using the PondService directly in the components makes it harder to maintain your project and write e2e and unit tests for your components.

???? Example:

Logic:

File: app.component.ts

import { Component } from '@angular/core';
import { ActyxPondService } from '@actyx-contrib/ng-pond'
import { MachineFish, State } from '../fish/MachineFish';
import { Observable } from 'rxjs';
import { ConnectivityStatus } from '@actyx/pond';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  machine$: Observable<State>
  connectivity$: Observable<ConnectivityStatus>

  constructor(private pondService: ActyxPondService) {
    this.machine$ = this.pondService.observe$(MachineFish.of('Machine1'))
    this.connectivity$ = this.pondService.getNodeConnectivity$()
  }

  async start() {
    const pond = await this.pondService.getPond()
    MachineFish.emitProdStartedEvent(pond, 'Machine1', 'order1')
  }

  async stop() {
    const pond = await this.pondService.getPond()
    MachineFish.emitProdStoppedEvent(pond, 'Machine1', 'order1')
  }
}
Template:

File: app.component.html

<h1>Angular - Actyx-Pond - Machine control</h1>
<div *ngIf="connectivity$ | async as connectivity">
  <h2>Connectivity: {{connectivity.status | json}}</h2>
</div>
<div *ngIf="machine$ | async as machine; else loading">
  <div>
    <h2>Machine {{machine.machineId}}</h2>
    <dl>
      <dt>state:</dt>
      <dd>{{machine.state}}</dd>
    </dl>
  </div>
  <button *ngIf="machine.state==='stopped'" (click)="start()">start</button>
  <button *ngIf="machine.state==='started'" (click)="stop()">stop</button>
</div>
<ng-template #loading>Loading machine data...</ng-template>
???? Fish

File: MachineFish.ts

import { Fish, FishId, Pond, Tag } from '@actyx/pond'
export type State =
  | { state: 'idle', machineId: string }
  | { state: 'inProduction', machineId: string, orderId: string }
export type Event =
  | { eventType: 'prodStarted', machineId: string, orderId: string }
  | { eventType: 'prodStopped', machineId: string, orderId: string }

const machineTag = Tag<Event>('machine')

export const MachineFish = {
  tags: { machineTag },
  of: (machineId: string): Fish<State, Event> => ({
    fishId: FishId.of('machineFish', machineId, 0),
    initialState: { state: 'idle', machineId },
    where: machineTag.withId(machineId),
    onEvent: (state, event) => {
      switch (event.eventType) {
        case 'prodStarted':
          return {
            state: 'inProduction',
            machineId: state.machineId,
            orderId: event.orderId,
          }
        case 'prodStopped':
          return {
            state: 'idle',
            machineId: state.machineId,
          }
      }
      return state
    },
  }),
  emitProdStoppedEvent: (pond: Pond, machineId: string, orderId: string) =>
    pond.emit(
      machineTag.withId(machineId),
      { eventType: 'prodStopped', machineId, orderId }
    ),
  emitProdStartedEvent: (pond: Pond, machineId: string, orderId: string) =>
    pond.emit(
      machineTag.withId(machineId),
      { eventType: 'prodStarted', machineId, orderId }
    ),
}

Registry fish

In the pond, there are two ways to create registry fish. observeAll and observe a registry fish and map the entity fish as a second step. In the matter that observeAll is pretty strate forward, here is an example for the registry fish.

???? Example:

Note: This example is build on top of the Use the pond api example above.

Logic:

File: app.component.ts

// [..]
  allMachines$: Observable<ReadonlyArray<State>>

  constructor(private pondService: ActyxPondService) {
    this.machine$ = this.pondService.observe$(MachineFish.of('Machine1'))
    this.allMachine$ = this.pondService.observeRegistry$(MachineFish.registry(), s => s, MachineFish.of)
    this.connectivity$ = this.pondService.getNodeConnectivity$()
  }
// [..]
}
Template:

File: app.component.html

<!-- [..] -->
<div *ngFor="let machine of (allMachines$ | async)">
  <dl>
    <dt>Name:</dt>
    <dd>{{machine.machineId}}</dd>
    <dt>State:</dt>
    <dd>{{machine.state}}</dd>
  </dl>
</div>
<!-- [..] -->
???? Fish

File: MachineFish.ts

export const MachineFish = {
  // [..]
  registry: (): Fish<string[], Event> => ({
    fishId: FishId.of('machineRegFish', 'reg', 0),
    initialState: [],
    where: machineTag,
    onEvent: (state, event) => {
      if (!state.includes(event.machineId)) {
        state.push(event.machineId)
      }
      return state
    },
  }),
  // [..]

???? Service overview

Check out the documentation about the Actyx-Pond to get more detailed information https://developer.actyx.com/docs/pond/introduction/

You are going to find a detailed api documentation in the definition file of the package.

TS/JS Promise interface:

  • getPond()
  • emit(tags, event)
  • observe(fish, onStateChanged)
  • observeRegistry(registryFish, mapToProperty, makeEntityFish, onStateChanged)
  • observeAll(seedEventsSelector, makeFish, opts, onStateChanged)
  • observeOne(seedEventSelector, makeFish, onStateChanged, stoppedByError)
  • getPondState(callback)
  • pondInfo()
  • run(fish, fn)
  • keepRunning(fish, fn, autoCancel)

RxJs integration:

Note: Not every function has a RxJs wrapper. In this case, please use the one from above.

  • getRxPond()
  • observeRegistry$(registryFish, mapToProperty, makeEntityFish)
  • observe$(fish)
  • observeAll$(seedEventsSelector, makeFish, opts)
  • observeOne$(seedEventsSelector, makeFish)
  • getPondState$()
  • getNodeConnectivity$()
  • waitForSwarmSync$()
  • run$(fish, fn)
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文