This commit is contained in:
crusader 2017-07-25 19:28:27 +09:00
parent 96f20d5784
commit f62e9216bd
15 changed files with 94 additions and 62 deletions

View File

@ -1,5 +1,8 @@
import { ReducersMapObject } from 'redux'; import { ReducersMapObject } from 'redux';
import { SagaWatcher } from '@overflow/commons/redux-saga';
import signInReducer from '@overflow/member/redux/reducer/signIn'; import signInReducer from '@overflow/member/redux/reducer/signIn';
import signInSagaWatchers from '@overflow/member/redux/saga/signIn';
// Container Configuration // Container Configuration
export interface ContainerConfig { export interface ContainerConfig {
@ -21,17 +24,23 @@ const rpcConfig: RPCConfig = {
export interface ReduxConfig { export interface ReduxConfig {
state: ReduxState; state: ReduxState;
reducerMaps: ReducersMapObject[]; reducerMaps: ReducersMapObject[];
sagaWarchers: (SagaWatcher[])[];
} }
export interface ReduxState { export interface ReduxState {
} }
const reduxState: ReduxState = {}; const reduxState: ReduxState = {};
const reduxConfig: ReduxConfig = { const reduxConfig: ReduxConfig = {
state: reduxState, state: reduxState,
reducerMaps: [ reducerMaps: [
signInReducer, signInReducer,
], ],
sagaWarchers: [
signInSagaWatchers,
],
}; };

View File

@ -20,8 +20,15 @@ import {
import createSagaMiddleware, { import createSagaMiddleware, {
SagaMiddleware, SagaMiddleware,
SagaIterator,
} from 'redux-saga'; } from 'redux-saga';
import {
fork,
} from 'redux-saga/effects';
import { import {
createHashHistory, createHashHistory,
History, History,
@ -39,12 +46,10 @@ import AppContext from '@overflow/commons/context';
import * as AppContextLifecycleActions from '@overflow/commons/context/redux/action/lifecycle'; import * as AppContextLifecycleActions from '@overflow/commons/context/redux/action/lifecycle';
import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC'; import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC';
import ReducerContext from '@overflow/commons/redux/ReducerContext'; import ReducerContext from '@overflow/commons/redux/ReducerContext';
import { SagaWatcher } from '@overflow/commons/redux-saga';
import appConfig, { Config, ReduxState } from './config'; import appConfig, { Config, ReduxState } from './config';
import sagas from './redux/saga';
// import routes from './router';
import App from './views/App'; import App from './views/App';
injectTapEventPlugin(); injectTapEventPlugin();
@ -81,7 +86,8 @@ class Application {
this.displayLoading(); this.displayLoading();
this.context = await this.initContext(); this.context = await this.initContext();
// this.rpcClient = await this.initRpcClient(); this.rpcClient = await this.initRpcClient();
this.context.put(this.rpcClient);
await this.initRedux(); await this.initRedux();
@ -141,13 +147,21 @@ class Application {
Application.useReduxDevTools ? compose(middleware, window.devToolsExtension()) : middleware, Application.useReduxDevTools ? compose(middleware, window.devToolsExtension()) : middleware,
); );
// saga // saga
this.sagaMiddleware.run(sagas); this.sagaMiddleware.run(this.initReduxSagaWarchers, this.config.redux.sagaWarchers);
resolve(); resolve();
}); });
return init; return init;
} }
private * initReduxSagaWarchers(sagaWarchers: (SagaWatcher[])[]): SagaIterator {
for (let sagaWarcher of sagaWarchers) {
for (let warcher of sagaWarcher) {
yield fork(warcher);
}
}
}
private displayLoading(): void { private displayLoading(): void {
ReactDOM.render( ReactDOM.render(
<div style={{ <div style={{

View File

@ -1,8 +0,0 @@
import { SagaIterator } from 'redux-saga';
import { fork } from 'redux-saga/effects';
import { watchSignin as memberWatchSignin } from '@overflow/member/redux/saga/signIn';
export default function* sagas(): SagaIterator {
yield fork(memberWatchSignin);
}

View File

@ -10,9 +10,14 @@ abstract class Service {
} }
protected send(methodName: string, ...params: any[]): Promise<string> { protected send<T>(methodName: string, ...params: any[]): Promise<T> {
return new Promise<string>(resolve => { return this.webSocketRPC.Call(methodName, params)
resolve(''); .then(body => {
const o: T = JSON.parse(body);
return o;
})
.catch(e => {
throw e;
}); });
} }
} }

View File

@ -5,4 +5,4 @@ export const PARAM_TYPES = 'overflow:paramtypes';
export const DESIGN_PARAM_TYPES = 'design:paramtypes'; export const DESIGN_PARAM_TYPES = 'design:paramtypes';
// The type of the binding at design time // The type of the binding at design time
export const INJECT_TAG = 'inject'; export const INJECT_TAG = '__inject__';

View File

@ -5,13 +5,24 @@ export interface Config {
required?: boolean; required?: boolean;
} }
const inject = (config?: Config) => { const inject = (config?: Config) => {
return (target: Object, propertyKey: string | symbol, parameterIndex?: number): void => { return (target: Object, propertyKey: string | symbol, parameterIndex?: number): void => {
if (typeof parameterIndex === 'number') { if (typeof parameterIndex === 'number') {
// tagParameter(target, targetKey, index, metadata); // tagParameter(target, targetKey, index, metadata);
} else { } else {
let types = Reflect.getMetadata('design:type', target, propertyKey); if (Reflect.hasOwnMetadata(METADATA.INJECT_TAG, target)) {
let meta = Reflect.getMetadata(METADATA.INJECT_TAG, target);
} else {
let meta: string[];
}
let types = Reflect.getMetadata(METADATA.INJECT_TAG, target);
// Reflect.defineMetadata(METADATA.PARAM_TYPES, types, target);
console.log(types);
// tagProperty(target, targetKey, metadata); // tagProperty(target, targetKey, metadata);
} }
}; };

View File

@ -1,12 +1,28 @@
import * as METADATA from './constants';
class AppContext { class AppContext {
private static context: AppContext = null; private static context: AppContext = null;
private instanceMap: Map<string, Function>;
private constructor() { private constructor() {
this.instanceMap = new Map();
} }
public static getService<T>(): T { public put(instance: any, name?: string): void {
return null; if (typeof name !== 'string') {
if (instance instanceof Function) {
name = (<Function>instance).name;
}
}
this.instanceMap.set(name, instance);
}
public static getService<T>(clazz: {new(...args: any[]): T}): T {
let types = Reflect.getMetadata(METADATA.PARAM_TYPES, clazz);
let i = new clazz();
return i;
} }
public static get<T>(): T { public static get<T>(): T {
@ -15,10 +31,8 @@ class AppContext {
return null; return null;
} }
public static put<T>(instance: T): void { public static put(instance: any, name?: string): void {
AppContext.getContext().put(instance, name);
return null;
} }
public static getContext(): AppContext { public static getContext(): AppContext {

View File

@ -0,0 +1,3 @@
import { SagaIterator } from 'redux-saga';
export type SagaWatcher = () => SagaIterator;

View File

@ -6,7 +6,8 @@ interface ReducerItem<State> {
} }
class ReducerContext { class ReducerContext {
private static instance: ReducerContext = new ReducerContext(); private static readonly instance: ReducerContext = new ReducerContext();
private static readonly sagaActionKey: string = '@@redux-saga/SAGA_ACTION';
private reducerMap: Map<string, ReducerItem<any>[]>; private reducerMap: Map<string, ReducerItem<any>[]>;
private constructor() { private constructor() {
@ -26,7 +27,9 @@ class ReducerContext {
} }
public static reducer<State, A extends Action>(state: State, action: A): State { public static reducer<State, A extends Action>(state: State, action: A): State {
const actionType = action.type; const actionType: string = action.type;
const isSagaAction = action.hasOwnProperty(ReducerContext.sagaActionKey) ? action[ReducerContext.sagaActionKey] : false;
if (ReducerContext.getInstance().reducerMap.has(actionType)) { if (ReducerContext.getInstance().reducerMap.has(actionType)) {
let reducerItems = ReducerContext.getInstance().reducerMap.get(actionType); let reducerItems = ReducerContext.getInstance().reducerMap.get(actionType);
for (let reducerItem of reducerItems) { for (let reducerItem of reducerItems) {
@ -34,8 +37,10 @@ class ReducerContext {
state = reducer(state, action); state = reducer(state, action);
} }
} else { } else {
if (-1 === actionType.indexOf('@@')) {
console.log(`Reducer for [${actionType}] is not exist in the context.`); console.log(`Reducer for [${actionType}] is not exist in the context.`);
} }
}
return state; return state;
} }

View File

@ -1,19 +0,0 @@
import Action from './Action';
import * as Redux from 'redux';
// export type Reducer<S> = <A extends Action>(state: S, action: A) => S;
// export interface ReducersMapObject {
// [key: string]: Reducer<any>;
// }
const createReducer = <State>(initialState: State, handlers: Redux.ReducersMapObject): Redux.Reducer<State> => {
return <A extends Action>(state: State = initialState, action: A): State => {
if (handlers[action.type]) {
return handlers[action.type](state, action);
}
return state;
};
};
export default createReducer;

View File

@ -58,10 +58,8 @@ export default class WebSocketRPC {
this.requestQueue = new Map(); this.requestQueue = new Map();
} }
public Call(method: string, params: any[]): Promise<any> { public Call(method: string, params: any[]): Promise<string> {
return new Promise<string>((resolve, reject) => {
return new Promise<any>((resolve, reject) => {
const requestID = this.getRequestID(); const requestID = this.getRequestID();
let request = new ProtocolRequest<ID_TYPE>(RPCProtocol, requestID); let request = new ProtocolRequest<ID_TYPE>(RPCProtocol, requestID);
let req = new RPCRequest(method, params); let req = new RPCRequest(method, params);

View File

@ -12,12 +12,7 @@ export class MemberService extends Service {
} }
public signin(signinId: string, signinPw: string): Promise<Member> { public signin(signinId: string, signinPw: string): Promise<Member> {
return new Promise<Member>(resolve => { return this.send<Member>('signin', [signinId, signinPw]);
const json = this.send('signin', [signinId, signinPw]);
let member: Member;
// member = ........(json);
resolve(member);
});
} }
public signout(member: Member): Member { public signout(member: Member): Member {

View File

@ -9,13 +9,13 @@ import State from '../redux/state/SignIn';
import * as signinActions from '../redux/action/signIn'; import * as signinActions from '../redux/action/signIn';
export function mapStateToProps(state: any): SignInStateProps { export function mapStateToProps(state: any, ownProps?: any): SignInStateProps {
return { return {
}; };
} }
export function mapDispatchToProps(dispatch: Dispatch<any>): SigninDispatchProps { export function mapDispatchToProps(dispatch: Dispatch<any>, ownProps?: any): SigninDispatchProps {
return { return {
onSignIn: (signinId: string, signinPw: string) => { onSignIn: (signinId: string, signinPw: string) => {
dispatch(signinActions.request(signinId, signinPw)); dispatch(signinActions.request(signinId, signinPw));

View File

@ -1,6 +1,7 @@
import { SagaIterator } from 'redux-saga'; import { SagaIterator } from 'redux-saga';
import { call, Effect, fork, put, takeLatest } from 'redux-saga/effects'; import { call, Effect, fork, put, takeLatest } from 'redux-saga/effects';
import { SagaWatcher } from '@overflow/commons/redux-saga';
import AppContext from '@overflow/commons/context'; import AppContext from '@overflow/commons/context';
import Action from '@overflow/commons/redux/Action'; import Action from '@overflow/commons/redux/Action';
@ -18,7 +19,7 @@ function* signin(action: Action<SigninPayload>): SagaIterator {
// payload: {sendingRequest: true}, // payload: {sendingRequest: true},
// }); // });
const member = yield call(AppContext.getService<MemberService>().signin, signinId, signinPw); const member = yield call(AppContext.getService(MemberService).signin, signinId, signinPw);
// if (responseBody.token === undefined) { // if (responseBody.token === undefined) {
// throw new Error(MESSAGES.UNABLE_TO_FIND_TOKEN_IN_LOGIN_RESPONSE); // throw new Error(MESSAGES.UNABLE_TO_FIND_TOKEN_IN_LOGIN_RESPONSE);
@ -34,6 +35,10 @@ function* signin(action: Action<SigninPayload>): SagaIterator {
} }
} }
export function* watchSignin(): SagaIterator { function* watchSignin(): SagaIterator {
yield takeLatest(SigninActions.REQUEST, signin); yield takeLatest(SigninActions.REQUEST, signin);
} }
const sagaWatchers: SagaWatcher[] = [watchSignin];
export default sagaWatchers;