Redux-Saga Middleware -1 Teori

Bu teori kısmına isterseniz paketin mantığının kuruluğu olduğu "Saga Pattern" ini anlayarak başlayalım.

Aşağıdaki yazıda ayrıntıları ile yazılmış.

https://medium.com/devopsturkiye/microservice-mimarilerde-transaction-y%C3%B6netimi-nas%C4%B1l-yap%C4%B1l%C4%B1r-228317e248ed

Bu yazı üzerinden Saga özelinde kısa bir özet yaparsak;

Farklı transactionların zincirleme olarak event mekanizmaları üzerinden başarılı ve başarısız senaryolara göre budaklanması ve yönetilmesidir. Burada React özelinde bir transactionımız olmayacak dolayısıyla aslında actionları yönetiyor olacağız.

Şimdi biraz React JS Redux ile neler yapıyorduk hatırlayalım hem de niye Redux-saga sorusunu soralım kendimize.  


 * Action tanımlanması

 * Action ın önyüzden dispatch edilerek çağrılması

 * Reducer ın store u kullanarak action ı karşılaması

 * Reducer içi yapılan işlemler 

 * Yeni state aktarımı ve tutulması

 * Yeni state in önyüzde gösterimi


Burada basit olarak reducer a gelen action ı yöneterek başarılı,başarısız veya beklemede olan isteklerimizi yönetebiliyor ve state güncellemelerini de önyüzümüze aktarabiliyoruz evet buraya kadar güzel.

Herşey bu kadar basit mi tabii ki değil. Anlık kesinti kaynaklı isteklerin tekrar gönderilmesi, daha önce yapılan işlerin geri alınması , gelen isteğin çoklanarak bir flow gibi takip edilmesi gibi komplike işler için bir middleware e ihtiyaç duyuyoruz. Böylece reducer a gelen istek saga ya iletilerek bu middleware altyapısı üzerinde çalışması sağlanıyor.

Redux-Saga yı anasayfası üzerinden tanıtalım.

Redux-Saga - An intuitive Redux side effect manager. | Redux-Saga

npm ya da yarn  ile paketi download edebilirsiniz.

npm install redux-saga 

yarn add redux-saga


Midlleware i register etmek için  aşağıdaki kodu kullanıyorsunuz.Burada bulunan sitedeki örnek kodda "sagas" altındaki mySaga yı import ederek gelen actionların reducerdan sonra ilgili action a ait watcher a düşmesi sağlanıyor.


import { createStore, applyMiddleware } from 'redux'

import createSagaMiddleware from 'redux-saga'

import reducer from './reducers'

import mySaga from './sagas'

// create the saga middleware

const sagaMiddleware = createSagaMiddleware()

// mount it on the Store

const store = createStore(

  reducer,

  applyMiddleware(sagaMiddleware)

)

// then run the saga

sagaMiddleware.run(mySaga)

// render the application


Bu kod bloğunda USER_FETCH_REQUESTED actionının middleware girmesi sağlanıyor.


* yield takeEvery ile tüm USER_FETCH_REQUESTED actionları fetchUser methoduna giriyor.

* yield call dış ortam çağrımızı gerçekleştiriyoruz.

* yield put ile başarılı olan USER_FETCH_SUCCEEDED e

                       başarısızlar USER_FETCH_FAILED tarafından çağrılıyor.


import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'

import Api from '...'

// worker Saga: will be fired on USER_FETCH_REQUESTED actions

function* fetchUser(action) {

   try {

      const user = yield call(Api.fetchUser, action.payload.userId);

      yield put({type: "USER_FETCH_SUCCEEDED", user: user});

   } catch (e) {

      yield put({type: "USER_FETCH_FAILED", message: e.message});

   }

}

/* Starts fetchUser on each dispatched `USER_FETCH_REQUESTED` action.

Allows concurrent fetches of user.

*/

function* mySaga() {

  yield takeEvery("USER_FETCH_REQUESTED", fetchUser);

}

/* Alternatively you may use takeLatest. Does not allow concurrent fetches of user. If "USER_FETCH_REQUESTED" gets dispatched while a fetch is already pending, that pending fetch is cancelled and only the latest one will be run. */

function* mySaga() {

  yield takeLatest("USER_FETCH_REQUESTED", fetchUser);

}

export default mySaga;


Bu örnek aslında standart redux mimarimizde yaptığımız işlemlerden çok farklı değil tabii.

Ancak biraz daha derli toplu oldu sanki :)

Şimdi retry mekanizması ekleyelim. Gördüğünüz gibi anlık kesinti için bir önlem almış olduk.


import { retry, put, takeEvery, takeLatest } from 'redux-saga/effects'

import Api from '...'

// worker Saga: will be fired on USER_FETCH_REQUESTED actions

function* fetchUser(action) {

   try {

     const user = yield retry(3, 10 * SECOND, Api.fetchUser, action.payload.userId);

      yield put({type: "USER_FETCH_SUCCEEDED", user: user});

   } catch (e) {

      yield put({type: "USER_FETCH_FAILED", message: e.message});

   }

}

İkinci yazımız ve örnek mini proje.

http://buraktunali.blogspot.com/2021/08/redux-saga-middleware-2-handson.html

Yorumlar

Bu blogdaki popüler yayınlar

IONIC BAŞLANGIÇ

Cannot resolve the collation conflict between “Turkish_CI_AS” and “SQL_Latin1_General_CP1_CI_AS” in the equal to operation

Golang working with interfaces and functions -3