Serivce

本节主要讲如何定义一个Service ?

简单的Service

interface State {
  // 定义State的类型
}
class DemoService extends Service<State> {
   defaultState: State =  {
     // 实现State
   }
}

上面是一个Service最基本的代码,defaultState是整个service的初始数据,必须提供

defaultState是readonly的,在整个Service生命周期中都不会改变,因此不要试图去直接修改this.defaultState的值。

Reducer

reducer 同redux里面的reducer,由当前的state通过一系列reducer逻辑返回一个全新的state:

interface State {
  count: number
}
class DemoService extends Service<State>{
   defaultState: State ={
     count: 0
   }
   @Reducer()
   add(state:State, x: number):State {
     return { count: state.count + x }
   }
   @Reducer()
   reset():State {
     return this.defaultState
   }
}

ImmerReducer

reducer比较占用内存,同时当state结构复杂之后进行reducer也是一件十分困难的事情,因此这里引入了一个immutable方案,作用与reducer一致,不过你可以在函数里面直接修改state:

interface State {
  count: number
}
class DemoService extends Service<State>{
   defaultState: State ={
     count: 0
   }
   
   @Reducer()
   add1(state:State, x: number):State {
     return { count: state.count + x }
   }
   
   @ImmerReducer()
   add2(state:State, x: number) {
     state.count += x
   }
}

add1和add2作用完全一致

Effect

Effect用于处理副作用

interface State {
  count: number
}
const fetchRemoteCount = ({level: number}) => from(fetch(`https://xxxxx?level=${level}`))

class DemoService extends Service<State>{
   defaultState: State ={
     count: 0
   }
   @ImmerReducer()
   setCount(state:State, x: number) {
     state.count = x
   }
   
   @Effect()
   getRemoteCount(level$: Observable<number>, state$: Observable<State>): Observable<EffectAction> {
     return level$.pipe(
         switchMap(level => fetchRemoteCount({level})),
         map(count => this.actions().setCount(count))
     )
   }
}

// 调用
const demoService = // 获取DemoService实例
const actions = demoService.getActionMethods()
actions.getRemoteCount(1)
actions.getRemoteCount(2)
//...

以上就是一个简单的请求api的例子, 下边actions每一次调用getRemoteCount(x)的时候,level$流都会推出一个x,然后通过switchMap操作符,这个符号就会对之前fetchRemoteCount 产生的流进行unsubscribe(对应具体的rx请求库就会自动cancel正在进行的请求)并再次调用fetchRemoteCount({level})产生一个 新流,并马上切换到这个新流上。

然后,使用map操作符将请求获取的结果count转化为EffectAction

Notice #1: this.actions()

this.actions()函数的返回是一个actionCreator集合,调用这些actionCreator可以得到一个action描述对象(EffectAction),如:

this.actions().setCount(2) // 将会返回一个setCount的actionCreator:
{
    service: demoService, // 当前action对应的service实例
    actionName: 'setCount', // 触发action的名字
    params: 2, // 触发action的调用参数
}

Last updated

Was this helpful?