ez-saga 18.0.5 → 18.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,9 @@
1
+ /**
2
+ * 判断是否为标准Action
3
+ */
4
+ function isAction(action) {
5
+ return typeof action === 'object' && action !== null && 'type' in action;
6
+ }
1
7
  /**
2
8
  * 创建中间层
3
9
  * @param registedModel 已注册model
@@ -6,22 +12,18 @@ function createPromiseMiddleware(registedModel) {
6
12
  function isEffect(type) {
7
13
  if (!type || typeof type !== 'string')
8
14
  return false;
15
+ // 性能优化:快速排除不包含 '/' 的普通 Action
16
+ if (type.indexOf('/') === -1)
17
+ return false;
9
18
  const [modelName, effect] = type.split('/');
10
19
  const model = registedModel[modelName];
11
- if (model) {
12
- if (model.effects && model.effects[effect]) {
13
- return true;
14
- }
20
+ if (model && model.effects && model.effects[effect]) {
21
+ return true;
15
22
  }
16
23
  return false;
17
24
  }
18
25
  return (api) => (next) => (action) => {
19
- let exeEffect = false;
20
- if (action?.type !== undefined) {
21
- const { type } = action;
22
- exeEffect = isEffect(type);
23
- }
24
- if (exeEffect) {
26
+ if (isAction(action) && isEffect(action.type)) {
25
27
  return new Promise((resolve, reject) => {
26
28
  next({
27
29
  _dy_resolve: resolve,
@@ -30,9 +32,7 @@ function createPromiseMiddleware(registedModel) {
30
32
  });
31
33
  });
32
34
  }
33
- else {
34
- return next(action);
35
- }
35
+ return next(action);
36
36
  };
37
37
  }
38
38
  export default createPromiseMiddleware;
@@ -1 +1 @@
1
- {"version":3,"file":"PromiseMiddleware.js","sourceRoot":"","sources":["../../src/redux/PromiseMiddleware.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,SAAS,uBAAuB,CAAqB,aAA4B;IAC/E,SAAS,QAAQ,CAAC,IAAY;QAC5B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACpD,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3C,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,GAA0B,EAAE,EAAE,CAAC,CAAC,IAA8B,EAAE,EAAE,CAAC,CAAC,MAAe,EAAE,EAAE;QAC7F,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAK,MAAiB,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAgB,CAAC;YAClC,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,IAAI,CAAC;oBACH,WAAW,EAAE,OAAO;oBACpB,UAAU,EAAE,MAAM;oBAClB,GAAG,MAAgB;iBACpB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"PromiseMiddleware.js","sourceRoot":"","sources":["../../src/redux/PromiseMiddleware.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,SAAS,QAAQ,CAAC,MAAe;IAC/B,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,MAAM,CAAC;AAC3E,CAAC;AAED;;;GAGG;AACH,SAAS,uBAAuB,CAAqB,aAA4B;IAC/E,SAAS,QAAQ,CAAC,IAAY;QAC5B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAEpD,8BAA8B;QAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAE3C,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,KAAK,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,GAA0B,EAAE,EAAE,CAAC,CAAC,IAA8B,EAAE,EAAE,CAAC,CAAC,MAAe,EAAE,EAAE;QAC7F,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,IAAI,CAAC;oBACH,WAAW,EAAE,OAAO;oBACpB,UAAU,EAAE,MAAM;oBAClB,GAAG,MAAM;iBACV,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC,CAAC;AACJ,CAAC;AAED,eAAe,uBAAuB,CAAC"}
@@ -1,28 +1,30 @@
1
- import { legacy_createStore as createStore, applyMiddleware, compose } from 'redux';
2
- import { createSlice, combineReducers } from '@reduxjs/toolkit';
1
+ import { configureStore, createSlice, combineReducers } from '@reduxjs/toolkit';
3
2
  import createSagaMiddleware from 'redux-saga';
4
3
  import { call, put, select, takeEvery, putResolve } from 'redux-saga/effects';
5
- import win from 'global/window';
6
4
  import saveState from './defaultReducer';
7
5
  import createPromiseMiddleware from './PromiseMiddleware';
6
+ // 提取公共的 Effect 工具对象,避免在循环中重复创建
7
+ const opFun = { call, put, putResolve, select };
8
+ /**
9
+ * 统一处理 Effect 的 Generator 函数
10
+ * 提取到外部以减少闭包创建,提升性能
11
+ */
12
+ function* handleEffect(modelName, effectFunc, tools, action) {
13
+ // 开始异步任务设置loading状态
14
+ yield putResolve({ type: `${modelName}/saveState`, payload: { loading: true } });
15
+ // 执行 Effect (支持 Generator 或 Promise)
16
+ const ret = yield call(effectFunc, action, tools);
17
+ // 结束异步任务关闭loading状态
18
+ yield putResolve({ type: `${modelName}/saveState`, payload: { loading: false } });
19
+ // 处理 PromiseMiddleware 的回调
20
+ if (action._dy_resolve) {
21
+ action._dy_resolve(ret);
22
+ }
23
+ }
8
24
  /**
9
25
  * 获取注册model函数
10
- * @param store redux store
11
- * @param registedModel 已注册model, 对象, 属性为model名称, value为model
12
- * @param allReducers 所有的reducers
13
- * @param sagaMiddleware saga中间件
14
- * @returns 返回function regist(model)
15
26
  */
16
27
  function getRegistModelFunc(store, registedModel, allReducers, sagaMiddleware) {
17
- /** model函数注册函数
18
- * @param model 模块, 其格式为
19
- * {
20
- * name: 'name',
21
- * state: {},
22
- * reducers: {},
23
- * effects: {}
24
- * }
25
- */
26
28
  return function regist(reduxModel) {
27
29
  const model = {
28
30
  ...reduxModel,
@@ -31,76 +33,64 @@ function getRegistModelFunc(store, registedModel, allReducers, sagaMiddleware) {
31
33
  if (registedModel[model.name]) {
32
34
  return;
33
35
  }
34
- if (!model.state) {
36
+ // 初始化模型属性
37
+ if (!model.state)
35
38
  model.state = {};
36
- }
37
39
  model.initialState = model.state;
38
- if (!model.reducers) {
40
+ if (!model.reducers)
39
41
  model.reducers = {};
40
- }
41
- if (!model.reducers.saveState) {
42
+ // 注入默认的 saveState reducer
43
+ if (!model.reducers.saveState)
42
44
  model.reducers.saveState = saveState;
43
- }
44
- if (!model.effects) {
45
+ if (!model.effects)
45
46
  model.effects = {};
46
- }
47
- const modelSlice = createSlice(model);
48
- const reducer = modelSlice.reducer;
49
- allReducers[model.name] = reducer;
47
+ // 使用 Redux Toolkit 创建 Slice
48
+ const modelSlice = createSlice({
49
+ name: model.name,
50
+ initialState: model.initialState,
51
+ reducers: model.reducers
52
+ });
53
+ // 注册 Reducer
54
+ allReducers[model.name] = modelSlice.reducer;
50
55
  registedModel[model.name] = model;
51
- //获得一个新的reducer, 将所有的reducer整合成一个
52
- let newReducer = combineReducers(allReducers);
56
+ // 动态更新 Store 的 Reducers
57
+ const newReducer = combineReducers(allReducers);
53
58
  store.replaceReducer(newReducer);
54
- //注册effects
55
- for (let effect in model.effects) {
56
- let type = `${model.name}/${effect}`;
57
- let execFun = model.effects[effect];
58
- function* loading(opFun, action) {
59
- // 开始异步任务设置loading状态
60
- yield putResolve({ type: `${model.name}/saveState`, payload: { loading: true } });
61
- let ret = yield call(execFun, action, opFun);
62
- // 结束异步任务关闭loading状态
63
- yield putResolve({ type: `${model.name}/saveState`, payload: { loading: false } });
64
- if (action._dy_resolve) {
65
- action._dy_resolve(ret);
66
- }
67
- }
68
- function* runEffect() {
69
- //yield takeLatest(type, loading, { call, put, putResolve, select });
70
- yield takeEvery(type, loading, { call, put, putResolve, select });
71
- }
72
- sagaMiddleware.run(runEffect);
59
+ // 注册 Effects
60
+ for (const effectKey in model.effects) {
61
+ const type = `${model.name}/${effectKey}`;
62
+ const effectFunc = model.effects[effectKey];
63
+ sagaMiddleware.run(function* () {
64
+ // 使用 takeEvery 的参数传递功能,将上下文传入 handleEffect
65
+ // handleEffect(modelName, effectFunc, tools, action)
66
+ yield takeEvery(type, handleEffect, model.name, effectFunc, opFun);
67
+ });
73
68
  }
74
69
  };
75
70
  }
76
71
  /** 创建store */
77
72
  export default function create() {
78
- //已经注册的reducer, key是名字, value是reducer
79
73
  const allReducers = {};
80
- //已注册model
81
74
  const registedModel = {};
82
75
  const sagaMiddleware = createSagaMiddleware();
83
76
  const promiseMiddleware = createPromiseMiddleware(registedModel);
84
- const middlewares = [
85
- promiseMiddleware,
86
- sagaMiddleware
87
- ];
88
- // eslint-disable-next-line no-undef
89
- const composeEnhancers = process.env.NODE_ENV !== 'production'
90
- && win.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
91
- win.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ trace: true, maxAge: 30 }) : compose;
92
- const enhancers = [applyMiddleware(...middlewares)];
93
- //redux store
94
- const store = createStore(saveState, {}, composeEnhancers(...enhancers));
77
+ // 使用 configureStore 替代 createStore
78
+ // 自动集成 Redux DevTools,自动组合中间件
79
+ const store = configureStore({
80
+ reducer: saveState, // 初始 Reducer
81
+ middleware: (getDefaultMiddleware) => getDefaultMiddleware({
82
+ thunk: false, // 禁用默认的 thunk,因为我们使用 saga
83
+ serializableCheck: false, // 禁用序列化检查,因为 action 中可能包含回调函数 (_dy_resolve)
84
+ immutableCheck: false // 禁用不可变检查,提升开发环境性能
85
+ }).concat(promiseMiddleware, sagaMiddleware),
86
+ devTools: process.env.NODE_ENV !== 'production',
87
+ preloadedState: {}
88
+ });
95
89
  const regist = getRegistModelFunc(store, registedModel, allReducers, sagaMiddleware);
96
- let app = {
97
- /** redux store */
98
- store: store,
99
- /** saga中间件 */
100
- sagaMiddleware: sagaMiddleware,
101
- /** model注册函数 */
102
- regist: regist
90
+ return {
91
+ store,
92
+ sagaMiddleware,
93
+ regist
103
94
  };
104
- return app;
105
95
  }
106
96
  //# sourceMappingURL=createApp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createApp.js","sourceRoot":"","sources":["../../src/redux/createApp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createApp.js","sourceRoot":"","sources":["../../src/redux/createApp.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ez-saga",
3
- "version": "18.0.5",
3
+ "version": "18.0.6",
4
4
  "description": "The ez-saga project is a project that imitates dva-js",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -31,32 +31,17 @@
31
31
  "@reduxjs/toolkit": "^2.11.2",
32
32
  "redux": "^5.0.1",
33
33
  "redux-saga": "^1.4.2",
34
- "global": "^4.4.0"
34
+ "tslib": "^2.8.1"
35
35
  },
36
- "peerDependencies": {},
37
36
  "devDependencies": {
38
- "@babel/core": "^7.23.7",
39
- "@babel/eslint-parser": "^7.23.3",
40
- "@babel/plugin-proposal-decorators": "^7.23.7",
41
- "@babel/plugin-syntax-flow": "^7.23.3",
42
- "@babel/plugin-transform-runtime": "^7.23.7",
43
- "@babel/preset-env": "^7.23.8",
44
- "@babel/preset-flow": "^7.23.3",
45
- "@babel/preset-typescript": "^7.23.3",
46
- "@babel/runtime-corejs3": "^7.23.8",
47
- "@babel/plugin-transform-class-properties": "^7.23.3",
48
- "@babel/plugin-transform-private-methods": "^7.23.3",
49
- "@babel/plugin-transform-private-property-in-object": "^7.23.4",
50
- "cross-env": "^7.0.3",
51
- "eslint": "^8.56.0",
52
- "eslint-plugin-flowtype": "^8.0.3",
53
- "eslint-plugin-import": "^2.29.1",
37
+ "@types/node": "^25.0.3",
54
38
  "eslint-plugin-node": "^11.1.0",
55
39
  "eslint-plugin-standard": "^4.1.0",
40
+ "rimraf": "^6.1.2",
56
41
  "typescript": "^5.3.3"
57
42
  },
58
43
  "engines": {
59
- "node": ">= 14.0.0",
44
+ "node": ">= 18.0.0",
60
45
  "npm": ">= 6.0.0"
61
46
  },
62
47
  "browserslist": [
@@ -68,7 +53,6 @@
68
53
  "files": [
69
54
  "lib",
70
55
  "src",
71
- "index.js",
72
56
  "tsconfig.json",
73
57
  "typing.d.ts"
74
58
  ]
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- /// <reference path="./global-shim.d.ts" />
1
+
2
2
  export { PayloadAction, EffectTool, Effect, ModelReducer, ModelEffect, ReduxModel, ReduxApp } from './redux/typeDeclare';
3
3
  export { Dispatch, Action } from 'redux';
4
4
  import createApp from './redux/createApp';
@@ -1,6 +1,13 @@
1
- import { Dispatch, Middleware, MiddlewareAPI, Action } from 'redux';
1
+ import { Dispatch, Middleware, MiddlewareAPI, Action, UnknownAction } from 'redux';
2
2
  import { RegistedModel } from './typeDeclare';
3
3
 
4
+ /**
5
+ * 判断是否为标准Action
6
+ */
7
+ function isAction(action: unknown): action is Action<string> {
8
+ return typeof action === 'object' && action !== null && 'type' in action;
9
+ }
10
+
4
11
  /**
5
12
  * 创建中间层
6
13
  * @param registedModel 已注册model
@@ -8,33 +15,29 @@ import { RegistedModel } from './typeDeclare';
8
15
  function createPromiseMiddleware<D extends Dispatch>(registedModel: RegistedModel): Middleware<any, any, any> {
9
16
  function isEffect(type: string) {
10
17
  if (!type || typeof type !== 'string') return false;
18
+
19
+ // 性能优化:快速排除不包含 '/' 的普通 Action
20
+ if (type.indexOf('/') === -1) return false;
21
+
11
22
  const [modelName, effect] = type.split('/');
12
23
  const model = registedModel[modelName];
13
- if (model) {
14
- if (model.effects && model.effects[effect]) {
15
- return true;
16
- }
24
+ if (model && model.effects && model.effects[effect]) {
25
+ return true;
17
26
  }
18
27
  return false;
19
28
  }
20
29
 
21
30
  return (api: MiddlewareAPI<D, any>) => (next: (action: unknown) => any) => (action: unknown) => {
22
- let exeEffect = false;
23
- if ((action as Action)?.type !== undefined) {
24
- const { type } = action as Action;
25
- exeEffect = isEffect(type);
26
- }
27
- if (exeEffect) {
31
+ if (isAction(action) && isEffect(action.type)) {
28
32
  return new Promise((resolve, reject) => {
29
33
  next({
30
34
  _dy_resolve: resolve,
31
35
  _dy_reject: reject,
32
- ...action as Action,
36
+ ...action,
33
37
  });
34
38
  });
35
- } else {
36
- return next(action);
37
39
  }
40
+ return next(action);
38
41
  };
39
42
  }
40
43
 
@@ -1,126 +1,122 @@
1
- import { legacy_createStore as createStore, applyMiddleware, compose, Action as ReduxAction, Store } from 'redux';
2
- import { createSlice, combineReducers } from '@reduxjs/toolkit';
1
+ import { configureStore, createSlice, combineReducers } from '@reduxjs/toolkit';
3
2
  import createSagaMiddleware, { SagaMiddleware } from 'redux-saga';
4
3
  import { call, put, select, takeEvery, putResolve } from 'redux-saga/effects';
5
- import win from 'global/window';
6
- import { Reducer, Action } from 'redux';
7
- import { ReduxModel, ReduxApp, RegistedModel, ReduxSagaModel, EffectTool, PayloadAction } from './typeDeclare';
4
+ import { Reducer, Action, Store } from 'redux';
5
+ import { ReduxModel, ReduxApp, RegistedModel, ReduxSagaModel, EffectTool, PayloadAction, Effect } from './typeDeclare';
8
6
  import saveState from './defaultReducer';
9
7
  import createPromiseMiddleware from './PromiseMiddleware';
10
8
 
9
+ // 提取公共的 Effect 工具对象,避免在循环中重复创建
10
+ const opFun: EffectTool = { call, put, putResolve, select };
11
+
12
+ /**
13
+ * 统一处理 Effect 的 Generator 函数
14
+ * 提取到外部以减少闭包创建,提升性能
15
+ */
16
+ function* handleEffect(
17
+ modelName: string,
18
+ effectFunc: Effect,
19
+ tools: EffectTool,
20
+ action: PayloadAction
21
+ ) {
22
+ // 开始异步任务设置loading状态
23
+ yield putResolve({ type: `${modelName}/saveState`, payload: { loading: true } });
24
+
25
+ // 执行 Effect (支持 Generator 或 Promise)
26
+ const ret: any = yield call(effectFunc, action, tools);
27
+
28
+ // 结束异步任务关闭loading状态
29
+ yield putResolve({ type: `${modelName}/saveState`, payload: { loading: false } });
30
+
31
+ // 处理 PromiseMiddleware 的回调
32
+ if (action._dy_resolve) {
33
+ action._dy_resolve(ret);
34
+ }
35
+ }
36
+
11
37
  /**
12
38
  * 获取注册model函数
13
- * @param store redux store
14
- * @param registedModel 已注册model, 对象, 属性为model名称, value为model
15
- * @param allReducers 所有的reducers
16
- * @param sagaMiddleware saga中间件
17
- * @returns 返回function regist(model)
18
39
  */
19
- function getRegistModelFunc(store: Store<any, ReduxAction>, registedModel: RegistedModel,
20
- allReducers: { [x: string]: Reducer<any, Action>; },
21
- sagaMiddleware: SagaMiddleware<object>): (model: ReduxModel) => void {
22
- /** model函数注册函数
23
- * @param model 模块, 其格式为
24
- * {
25
- * name: 'name',
26
- * state: {},
27
- * reducers: {},
28
- * effects: {}
29
- * }
30
- */
40
+ function getRegistModelFunc(
41
+ store: Store<any, Action<string>>,
42
+ registedModel: RegistedModel,
43
+ allReducers: { [x: string]: Reducer<any, any>; },
44
+ sagaMiddleware: SagaMiddleware<object>
45
+ ): (model: ReduxModel) => void {
31
46
  return function regist(reduxModel: ReduxModel): void {
32
47
  const model = {
33
48
  ...reduxModel,
34
49
  initialState: {}
35
50
  } as ReduxSagaModel;
51
+
36
52
  if (registedModel[model.name]) {
37
53
  return;
38
54
  }
39
- if (!model.state) {
40
- model.state = {};
41
- }
55
+
56
+ // 初始化模型属性
57
+ if (!model.state) model.state = {};
42
58
  model.initialState = model.state;
43
- if (!model.reducers) {
44
- model.reducers = {};
45
- }
46
- if (!model.reducers.saveState) {
47
- model.reducers.saveState = saveState;
48
- }
49
- if (!model.effects) {
50
- model.effects = {};
51
- }
52
- const modelSlice = createSlice(model);
53
- const reducer = modelSlice.reducer;
54
- allReducers[model.name] = reducer;
59
+ if (!model.reducers) model.reducers = {};
60
+ // 注入默认的 saveState reducer
61
+ if (!model.reducers.saveState) model.reducers.saveState = saveState;
62
+ if (!model.effects) model.effects = {};
63
+
64
+ // 使用 Redux Toolkit 创建 Slice
65
+ const modelSlice = createSlice({
66
+ name: model.name,
67
+ initialState: model.initialState,
68
+ reducers: model.reducers as any
69
+ });
70
+
71
+ // 注册 Reducer
72
+ allReducers[model.name] = modelSlice.reducer;
55
73
  registedModel[model.name] = model;
56
- //获得一个新的reducer, 将所有的reducer整合成一个
57
- let newReducer = combineReducers(allReducers);
74
+
75
+ // 动态更新 Store 的 Reducers
76
+ const newReducer = combineReducers(allReducers);
58
77
  store.replaceReducer(newReducer);
59
- //注册effects
60
- for (let effect in model.effects) {
61
- let type: string = `${model.name}/${effect}`;
62
- let execFun = model.effects[effect];
63
- function* loading(opFun: EffectTool, action: PayloadAction) {
64
- // 开始异步任务设置loading状态
65
- yield putResolve({ type: `${model.name}/saveState`, payload: { loading: true } });
66
- let ret = yield call(execFun, action, opFun);
67
- // 结束异步任务关闭loading状态
68
- yield putResolve({ type: `${model.name}/saveState`, payload: { loading: false } });
69
- if (action._dy_resolve) {
70
- action._dy_resolve(ret);
71
- }
72
- }
73
-
74
- function* runEffect() {
75
- //yield takeLatest(type, loading, { call, put, putResolve, select });
76
- yield takeEvery(type, loading, { call, put, putResolve, select });
77
- }
78
-
79
- sagaMiddleware.run(runEffect);
78
+
79
+ // 注册 Effects
80
+ for (const effectKey in model.effects) {
81
+ const type = `${model.name}/${effectKey}`;
82
+ const effectFunc = model.effects[effectKey];
83
+
84
+ sagaMiddleware.run(function* () {
85
+ // 使用 takeEvery 的参数传递功能,将上下文传入 handleEffect
86
+ // handleEffect(modelName, effectFunc, tools, action)
87
+ yield takeEvery(type, handleEffect, model.name, effectFunc, opFun);
88
+ });
80
89
  }
81
90
  };
82
91
  }
83
92
 
84
-
85
93
  /** 创建store */
86
94
  export default function create(): ReduxApp {
87
- //已经注册的reducer, key是名字, value是reducer
88
95
  const allReducers = {};
89
- //已注册model
90
96
  const registedModel: RegistedModel = {};
91
97
 
92
98
  const sagaMiddleware = createSagaMiddleware();
93
-
94
99
  const promiseMiddleware = createPromiseMiddleware(registedModel);
95
100
 
96
- const middlewares = [
97
- promiseMiddleware,
98
- sagaMiddleware
99
- ];
100
-
101
- // eslint-disable-next-line no-undef
102
- const composeEnhancers = process.env.NODE_ENV !== 'production'
103
- && win.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
104
- win.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ trace: true, maxAge: 30 }) : compose;
105
-
106
- const enhancers = [applyMiddleware(...middlewares)];
107
-
108
- //redux store
109
- const store = createStore(
110
- saveState,
111
- {},
112
- composeEnhancers(...enhancers)
113
- );
101
+ // 使用 configureStore 替代 createStore
102
+ // 自动集成 Redux DevTools,自动组合中间件
103
+ const store = configureStore({
104
+ reducer: saveState, // 初始 Reducer
105
+ middleware: (getDefaultMiddleware) =>
106
+ getDefaultMiddleware({
107
+ thunk: false, // 禁用默认的 thunk,因为我们使用 saga
108
+ serializableCheck: false, // 禁用序列化检查,因为 action 中可能包含回调函数 (_dy_resolve)
109
+ immutableCheck: false // 禁用不可变检查,提升开发环境性能
110
+ }).concat(promiseMiddleware, sagaMiddleware),
111
+ devTools: process.env.NODE_ENV !== 'production',
112
+ preloadedState: {}
113
+ });
114
114
 
115
115
  const regist = getRegistModelFunc(store, registedModel, allReducers, sagaMiddleware);
116
116
 
117
- let app: ReduxApp = {
118
- /** redux store */
119
- store: store,
120
- /** saga中间件 */
121
- sagaMiddleware: sagaMiddleware,
122
- /** model注册函数 */
123
- regist: regist
117
+ return {
118
+ store,
119
+ sagaMiddleware,
120
+ regist
124
121
  };
125
- return app;
126
122
  }
@@ -20,11 +20,6 @@ declare module 'redux' {
20
20
  }
21
21
  }
22
22
 
23
- // /** 定义AsyncDispatch, 使其兼容redux promiseMiddleware中间件修改返回结果的情况 */
24
- // export interface AsyncDispatch {
25
- // <R = any>(action: PayloadAction, ...extraArgs: any[]): Promise<R>;
26
- // }
27
-
28
23
  /** 工具 */
29
24
  export interface EffectTool {
30
25
  /** 调用异步函数, 并获得该异步函数的结果 */
@@ -1,10 +0,0 @@
1
- declare module 'global/window' {
2
- const window: Window & typeof globalThis;
3
- export default window;
4
- }
5
-
6
- interface Window {
7
- app: any;
8
- terminalType: string;
9
- __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: any;
10
- }
package/src/index.js DELETED
@@ -1,4 +0,0 @@
1
- import createApp from './redux/createApp';
2
- export default {
3
- createApp: createApp
4
- };