Introduction

In this section, you should learn

  • Definition of #redux#saga
  • Watchers in Saga are closely related to observer pattern that monitor actions as events
  • Subroutines in Saga are implementations of iterator pattern that manage async operation in synchronous style
  • Naming convention in Saga programming
  • Controlling concurrency and blocking flow
  • Triggering single subroutine in multiple watchers for the sake of while-loop
  • Bearing buffer action regulation in batch processing, like producer-consumer-model
  • Interrupting asynchronous subroutine with graceful procedure.

Enrich yourself daily

Playing games, as well as reading game magazines, is a good way to learn and experience Saga; whenever you see a feature, try to guess the flow control behind. In #Zelda

  • HpSaga manipulates the HP mutation of getting fire, battling with monsters, etc
  • WeaponSaga conducts the durability of your current stored weapon
  • WorldSaga controls the existence of various objects
  • GravitySaga direct how you and other monsters fall
  • BattleSaga takes APPROACH_TO_MONSTER action, and triggers the battle AI subroutine
  • Each MissionSaga and ShrineSaga observes selected actions closely
  • etc

Definition

Saga is observer, it triggers some side-effects when an action is dispatched

// old days
 monster.on('killed', (event) => {
     event.killer.weapon.durability(-1);
     event.monster.vanish();
     event.world.add(event.monster.rewards());
     event.killer.bloody(+1);
 });

 player.on('killed', (event) => {
     if (event.player.rebirth > 0){
         event.player.rebirth--;
         event.player.health = 0.5 * event.player.max_health;
     } else {
         event.gameover();
     }
 });
//new days

 function* weaponSaga(){
     while (true){
         const { monster }  = yield take (MONSTER_KILLED);
         yield put (WEAPON_DAMAGED, monster.hp * 0.2);
     }
 }
 function* lifeSaga(){
     while (true){
         const factor = yield race [MONSTER_DAMAGE, FALLING, BURNING, FREEZING, EATING];
         var currentHP = yield select((state) => state.currentHP);
         switch (factor){
             // manipulate currentHP
         }
         if (currentHP < 0){
             const rebirth = yield select((state) => state.rebirth);
             if (rebirth > 0){
                 yield put(REBIRTH);
             } else {
                 yield put(GAMEOVER);
                 // NavigationAction.go('/gameover')
             }
         } else {
             yield put(UPDATE_HP, currentHP)
         }
     }
 }

Each Saga has watcher

function* watchVerbNoun(){
    while (true){
        const {params} = yield take(actions.NOUN_VERB);
        yield fork(loadSth, params)
    }
}

export default function* root() {
    yield all([
        fork(watchVerbNoun),
        ...
    ])
}

In some cases, like prefetch and refresh, you may find a do-while-loop could reduce coding, yet elegant coder still writes while-loop. Why?

Each Saga has watcher, followed by subroutine

Examples

  1. Watcher and subroutine
    1. https://github.com/redux-saga/redux-saga/blob/master/examples/real-world/sagas/index.js
  2. Concurrent or blocking
    1. https://github.com/redux-saga/redux-saga/blob/master/examples/shopping-cart/src/sagas/index.js
  3. Prefetch and refresh
    1. https://github.com/redux-saga/redux-saga/blob/master/examples/async/src/sagas/index.js
  4. Buffer action or event
    1. https://github.com/redux-saga/redux-saga/blob/master/docs/advanced/Channels.md
  5. Cancellable counter
    1. https://github.com/redux-saga/redux-saga/blob/master/examples/cancellable-counter/src/sagas/index.js

results matching ""

    No results matching ""