О сагах ни слова

function loadTodos() {
  return dispatch => {
    dispatch({ type: 'FETCHING_TODOS' });
    fetch('/todos').then(todos => {
      dispatch({ type: 'FETCHED_TODOS', payload: todos });
    }); 
  }
}

Тесты?

Hector Garcia-Molina

& Kenneth Salem

1987

Long Lived Transactions

(LLTs)

БД

LLT

Сага это коллекция подопераций

T_1, T_2, ... , T_n
T1,T2,...,TnT_1, T_2, ... , T_n

У каждой подоперации есть компенсирующая составляющая

C_1, C_2, ... , C_n
C1,C2,...,CnC_1, C_2, ... , C_n

\(C_n\) фактически отменяет \(T_n\) 

Саги гарантируют

  • \(T_1, T_2, ... , T_n\) или

  • \(T_1, T_2, ... , T_j, C_j, ... , C_2, C_1\)

Удачный сценарий

Begin Saga                                  

Start Book Hotel (\(T_1\))

End Book Hotel (\(T_1\))

Start Book Car Rental (\(T_2\))

End Book Car Rental (\(T_2\))

Start Book Flight (\(T_3\))

End Book Flight (\(T_3\))

End Saga

🏨

🚘

✈️

🏨

🚘

✈️

Неудачный сценарий

Begin Saga

Start Book Hotel (\(T_1\))

End Book Hotel (\(T_1\))

Start Book Car Rental (\(T_2\))

Abort Saga

Start Compensate Car Rental (\(C_2\))

EndCompensate Car Rental (\(C_2\))

Start Compensate Book Hotel (\(C_1\))

End Compensate Book Hotel (\(C_1\))

End Saga

🏨

🚘

🚘

🏨

Генераторы

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

let one = generator.next();
alert(JSON.stringify(one)); // {value: 1, done: false}

let two = generator.next();
alert(JSON.stringify(two)); // {value: 2, done: false}

let three = generator.next();
alert(JSON.stringify(three)); // {value: 3, done: true}
function* generateSequence() {
  yield 1;
  yield 2;
  yield 3;
}

let generator = generateSequence();

for(let value of generator) {
  alert(value); // 1, затем 2, затем 3
}
function* gen() {
  let ask1 = yield "Сколько будет 2 + 2?";

  alert(ask1); // 4

  let ask2 = yield "3 * 3?"

  alert(ask2); // 9
}

let generator = gen();

alert( generator.next().value ); // "2 + 2?"

alert( generator.next(4).value ); // "3 * 3?"

alert( generator.next(9).done ); // true
function loadTodos() {
  return dispatch => {
    dispatch({ type: 'FETCHING_TODOS' });
    fetch('/todos').then(todos => {
      dispatch({ type: 'FETCHED_TODOS', payload: todos });
    }); 
  }
}
import { call, put } from 'redux-saga';

function* loadTodos() {
  yield put({ type: 'FETCHING_TODOS' });
  const todos = yield call(fetch, '/todos');
  yield put({ type: 'FETCHED_TODOS', payload: todos });
}
  • put - диспатчит экшен в Redux Store
  • call - выполняет асинхронную функцию (промис, другую сагу и т.д.)
import { expect } from "chai";
import { call, put } from 'redux-saga';

function* loadTodos() {
  yield put({ type: 'FETCHING_TODOS' });
  const todos = yield call(fetch, '/todos');
  yield put({ type: 'FETCHED_TODOS', payload: todos });
}

const mySaga = loadTodos();
const myTodos = [{ message: 'text', done: false }];
const action = { type: 'FETCHED_TODOS', payload: myTodos };

expect(mySaga.next().value).to.deep.equal(put({ type: 'FETCHING_TODOS' }));
expect(mySaga.next().value).to.deep.equal(call(fetch, '/todos')); 
expect(mySaga.next(myTodos).value).to.deep.equal(put(action));
expect(mySaga.next().done).to.be.true;

Call2Action

О сагах ни слова

By Alexander Sushko

О сагах ни слова

  • 712