thunk, saga ,Sequelize ,주요함수
thunk
액션 객체가 아닌 함수를 디스패치 할 수 있습니다.
코드 예시
```
const thunk = store => next => action =>
typeof action === 'function'
? action(store.dispatch, store.getState)
: next(action)
```
미들웨어를 사용하면 함수를 디스패치 할 수 있다고 했는데요, 함수를 디스패치 할 때에는,
해당 함수에서 dispatch
와 getState
를 파라미터로 받아와주어야 합니다.
이 함수를 만들어주는 함수를 우리는 thunk 라고 부릅니다.
사용 예시
const getComments = () => (dispatch, getState) => {
// 이 안에서는 액션을 dispatch 할 수도 있고
// getState를 사용하여 현재 상태도 조회 할 수 있습니다.
const id = getState().post.activeId;
// 요청이 시작했음을 알리는 액션
dispatch({ type: 'GET_COMMENTS' });
// 댓글을 조회하는 프로미스를 반환하는 getComments 가 있다고 가정해봅시다.
api
.getComments(id) // 요청을 하고
.then(comments => dispatch({ type: 'GET_COMMENTS_SUCCESS', id, comments })) // 성공시
.catch(e => dispatch({ type: 'GET_COMMENTS_ERROR', error: e })); // 실패시
};
async await 활용
const getComments = () => async (dispatch, getState) => {
const id = getState().post.activeId;
dispatch({ type: 'GET_COMMENTS' });
try {
const comments = await api.getComments(id);
dispatch({ type: 'GET_COMMENTS_SUCCESS', id, comments });
} catch (e) {
dispatch({ type: 'GET_COMMENTS_ERROR', error: e });
}
}
thunk 예제
const {createStore,compose,applyMiddleware} =require('redux')
const {rootReducer} = require('./reducers')
//thunk
//1. thunk 정의
const thunk =({dispatch,getState})=>(next)=>(action)=>(
typeof action === 'function'
? action(dispatch)
: next(action)
)
//2. 변수에 담기
const middleware = [thunk]
//3. compose를 사용해 enhancer을 만들어준다.
const enhancer = compose(applyMiddleware(...middleware)) //applyMiddleware 안에 함수가 들어감
//4. store에 rootReducer,enhancer를 담아준다.
const store = createStore(rootReducer,enhancer)
console.log(store.getState());
store.dispatch({type:'asda'})
store.dispatch({type:'asda'})
store.dispatch({type:'asda'})
store.dispatch({type:'asda'})
const aa = ()=>{
console.log('여기까지 가능');
const bb = (dispatch)=>{
dispatch({type:'나는 로그인할거임'})
}
return bb
}
store.dispatch(aa())
실행 후 모습

thunk compose
미들웨어란, 액션과 리듀서 사이에 존재합니다. 특정 액션을 가하고 리듀서가 처리하기 전에 작업을 처리합니다.
일반적으로 store를 생성하는 법
const store = createStore(reducer);
applyMiddleware를 활용하여 미들웨어를 거쳐가도록 하는 store 생성법
const store = createStore(RootReducer, applyMiddleware(promiseMiddleware, ReduxThunk))
SAGA
saga는 제너레이터 함수의 yield에서 call effect가 발생할때 promise가 resolve될 때까지 기다리다가,
완료되면 제너레이터의 next()를 호출하여 다음으로 이동한다.
dispatch 후에 함수를 추적해서 실행함
saga 기본 세팅
import saga from ‘redux-saga’
const {takeEvery,takeLatest, call, put} = require('redux-saga/effects')
saga 연습 gen.js
function* gen3(){
let a = yield
console.log(a);
let b = yield
console.log(b);
yield 3
yield 4
return 5
}
function* middle(){
console.log('접근');
while(true){
const action = yield;
if (action.type === 'ingoo'){
console.log('qudtls');
}
}
}
const a = middle()
const b = gen3()
콘솔창에서 a.next(‘ingoo’)라고 치면 그에 해당하는 콘솔로그 값이 나온다.
b.next(값) 도 똑같다.
saga 예제
const {createStore,compose,applyMiddleware} =require('redux')
const {rootReducer} = require('./reducers')
const reduxSaga = require('redux-saga')
const {takeEvery,takeLatest, call, put} = require('redux-saga/effects')
function loginAPI(id,pw){
return axios.post('url')
}
function* change(action){
const {payload:{id,pw}}=action
console.log(id,pw);
try{
const result = yield call(loginAPI(),id,pw)
//성공
yield put({type:'성공'})
}catch (e){
//실패
yield put({type:'실패'})
}
}
// SAGA
// import saga from 'redux-saga'
//dispatch 후에 함수를 추적해서 실행함
function* change(action){
console.log(action);
}
function* rootSaga(){
//1. action 상태를 확인 하고싶다.
//take 액션값이 같을경우, 특정함수를 호출하는 그런아이
// 1번째 인자값은 , type내용 ,2번째 인자값은 ,호출할 함수명 함수가 하나일때
console.log('hello world');
yield takeEvery('ingoo',change)
// yield takeLatest('ingoo',change)
}
const sagaMiddleware = reduxSaga.default()
const middleware = [sagaMiddleware]
const enhancer = compose(applyMiddleware(...middleware)) //applyMiddleware 안에 함수가 들어감
const store = createStore(rootReducer,enhancer)
sagaMiddleware.run(rootSaga)
store.dispatch({type:'ingoo'})

Sequelize DB에 연결
/*
ORM
sequelize = DBMS mysql,oracle,mssql,postgresql... 관리
mysql2
mysql.createPool('접속정보~')
nodejs 코드에서 > mysql 접속
SQL
webserver select 문을 작성해서 보냈다면
이것은 ORM find() = select * from 으로 보내준다.
mysql2 sequelize
*/
const {Sequelize, DataTypes}= require('sequelize')
//인자값이 4개임
//1. 데이터베이스명
//2. 데이터베이스 계정명 > mysql -u ssss
//3. 데이터베이스 패스워드
//4. Object 객체 넣음
//5. host 적어줌
//6. dialect:'mysql' 사용하는 db
const sequelize = new Sequelize('example','ingoo','ingoo',{
host:'localhost',
dialect:'mysql'
})
// sequelize.sync()
// .then(data=>{
// console.log('접속됨');
// }).catch(error =>{
// console.log('실패됨');
// })
async function init(){
try{
await sequelize.sync()
console.log('접속');
comment()
//코드를 작성하면 sequelize 코드를 다 실행할 수 있음,
}catch(e){
console.log('실패');
}
}
init()
function comment(){
//model 만들기
const USER = sequelize.define('comment',{
//field 내용
subject:{
type:DataTypes.STRING(30),
allowNull:false,
},
content:{
type:DataTypes.STRING(50),
allowNull:false
}
},{
//옵션 정보
tableName:'ingoo',
timestamps:false
})
return USER
}
const insert = async ()=>{
const USER = comment()
await USER.create({subject:'adsf',content:'asdf'})
}

yield
yield는 마치 return 처럼 동작하며 정해진 구간을 순서대로 실행하며 반드시 ‘function*’ 을 사용한 함수에서 사용합니다.
주요함수
delay
설정된 시간 이후에 resolve하는 Promise
객체를 리턴한다.
예시: delay(1000)
→ 1초 기다리기
put
특정 액션을 dispatch하도록 한다.
예시: put({type: 'INCREMENT]})
→INCREAMENT action을 dispatch한다.
takeEvery
들어오는 모든 액션에 대해 특정 작업을 처리해 준다.
예시: takeEvery(INCREASE_ASYNC, increaseSaga)
→들어오는 모든 INCREASE_ASYNC액션에 대해 increaseSaga 함수 실행
takeLatest
기존에 진행 중이던 작업이 있다면 취소 처리하고 가장 마지막으로 실행된 작업만 수행한다.
예시: takeLatest(DECREASE_ASYNC, decreaseSaga)
→DECREASE_ASYNC액션에 대해서 기존에 진행 중이던 작업이 있다면 취소 처리하고 가장 마지막으로 실행된 작업에 대해서만 decreaseSaga함수를 실행한다.
call
함수의 첫 번째 파라미터는 함수, 나머지 파라미터는 해당 함수에 넣을 인수이다.
예시: call(delay, 1000)
→delay(1000)함수를 call함수를 사용해서 이렇게 쓸 수도 있다.
call
과 put
의 다른 점은 put
은 스토어에 인자로 들어온 action을 dispatch하고, call
인 경우에는 주어진 함수를 실행하게 되는 것이다.
all
all
함수를 사용해서 제너레이터 함수를 배열의 형태로 인자로 넣어주면, 제너레이터 함수들이 병행적으로 동시에 실행되고, 전부 resolve될때까지 기다린다. Promise.all
과 비슷하다고 보면된다.
예시: yield all([testSaga1(), testSaga2()])
→ testSaga1()과 testSaga2()가 동시에 실행되고, 모두 resolve될 때까지 기다린다.