Created
August 15, 2018 18:03
-
-
Save zcherries/e8cd8c818907f2b0b21162b04b1a775b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Continuous iterator | |
function foo() { | |
// NOTE: don't ever do crazy long-running loops like this | |
for (let i = 0; i <= 1E10; i++) { | |
console.log(i); | |
} | |
} | |
// foo(); | |
// Generators: pause at yield statements and only continue when foo.next() is called. | |
// This allows you to iterate over infinitely large datasets without memory issues. | |
function* foo() { | |
// NOTE: don't ever do crazy long-running loops like this | |
let i=0; | |
for (i; i<=1E10; i++) { | |
yield console.log(i); | |
} | |
return i; | |
} | |
// Execution jumps in and out of a generator everywhere you see a yield statement. | |
// Think of a yield statement as causing the generator to pause and return the yielded value. | |
// Later on, the caller can resume the generator at the statement following the yield. | |
// When called initially, generator functions do not execute any of their code, | |
// instead returning a type of iterator called a Generator. | |
const generator = foo(); | |
// When a value is consumed by calling the generator's next method, | |
// the Generator function executes until it encounters the yield keyword. | |
const next = generator.next(); | |
// next() method returns an object with two properties | |
const next = { | |
value: 'the next value in the sequence', | |
done: false, // true if the last value in the sequence has already been consumed | |
}; | |
// The next() method also accepts a value which can be used to modify the internal state of the generator. | |
// A value passed to next() will be treated as the result of the last yield expression that paused the generator. | |
generator.next(true); | |
// Redux middleware | |
// Used to intercept dispatched actions coming into the store via the dispatch method, | |
// and can be used to handle asynchronous tasks. | |
// Redux Thunk vs Redux Sagas | |
// Thunk | |
// Chain callbacks | |
export const thunkName = | |
parameters => | |
(dispatch, getState) => { | |
// Your application logic goes here | |
}; | |
// When you dispatch a thunk, it calls the inner function. | |
import * as api from 'api'; | |
import { loginRequest, loginSuccess, loginFailure } from './loginActions'; | |
export const loginThunk = | |
(name: string, password: string) => | |
(dispatch: Function) => { | |
dispatch(loginRequest()); | |
try { | |
api.login(name, password); | |
} catch (err) { | |
dispatch(loginFailure(err)); | |
} | |
dispatch(loginSuccess()); | |
}; | |
// Cons: | |
// Callback hell makes reading them harder | |
// Testing thunks often requires complex mocking of the fetch api or other functions. | |
// Sagas | |
// Pros: readability and testing | |
// allows you to express complex application logic as pure functions called sagas. | |
// Pure functions are desirable from a testing standpoint because they are predictable and repeatable, | |
// which makes them relatively easy to test. | |
import * as api from 'api'; | |
import { LoginRequestAction, loginSuccess, loginFailure } from './loginActions'; | |
function* loginSaga() { | |
const action: LoginRequestAction = yield take('LOGIN_REQUEST'); | |
const { name, password } = action.payload; | |
try { | |
yield call(api.login, name, password); | |
} catch (err) { | |
yield put(loginFailure(err)); | |
return; | |
} | |
yield put(loginSuccess()); | |
} | |
// Once the login saga is registered with Redux-Saga, it will begin executing immediately. | |
// But then the yield take on the the first line will pause the saga until an | |
// action with type 'LOGIN_REQUEST' is dispatched to the store. Once that happens, execution will continue. | |
// Testing | |
// The 'call' and 'put' methods return javascript objects, | |
// so in unit tests you can simply test each value yielded by your saga function with equality comparison. | |
// No need to mock the api; | |
// 'Fork' execute an non-blocking process. | |
// | |
// 'Take' pause and wait for action coming. | |
// | |
// 'Call' invokes a function, which,if returns a Promise, stop execution and waits for the result. | |
// | |
// 'Put' invoke Action, like dispatch. | |
// | |
// 'Select' invoke in order to get state. | |
// | |
// 'takeLatest' return latest effect’s result. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment