mm_expand 2.0.1 → 2.0.2

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.
package/lib/base.js CHANGED
@@ -33,7 +33,7 @@ class Base extends Event {
33
33
 
34
34
  /**
35
35
  * 状态
36
- * @type {string} - 状态, 可选值: created, init, running, stopped
36
+ * @type {string} - 状态, 可选值: created, initing, starting, running, stopped, destroying, destroyed
37
37
  */
38
38
  this.status = 'created';
39
39
 
@@ -58,39 +58,54 @@ Base.prototype.log = function (level, message, ...args) {
58
58
  * 初始化监听
59
59
  */
60
60
  Base.prototype._initListen = function () {
61
+ let status_last = 'created';
62
+ // 初始化
61
63
  this.on('init:before', (ctx) => {
62
64
  this.status = 'initing';
63
65
  this._initCore(...ctx.params);
64
66
  });
67
+ this.on('init:after', (ctx) => {
68
+ this.status = 'inited';
69
+ });
70
+ // 启动
65
71
  this.on('start:before', (ctx) => {
72
+ status_last = this.status;
66
73
  this.status = 'starting';
67
74
  });
68
- this.on('start:after', (ctx) => {
75
+ this.on('start:success', (ctx) => {
69
76
  this.status = 'running';
70
77
  });
78
+ this.on('start:error', (ctx) => {
79
+ this.status = status_last;
80
+ });
81
+ // 停止
71
82
  this.on('stop:before', (ctx) => {
83
+ status_last = this.status;
72
84
  this.status = 'stopping';
73
85
  });
74
- this.on('stop:after', (ctx) => {
86
+ this.on('stop:success', (ctx) => {
75
87
  this.status = 'stopped';
76
88
  });
77
- this.on('restart:before', (ctx) => {
78
- this.status = 'restarting';
79
- });
80
- this.on('restart:after', (ctx) => {
81
- this.status = 'running';
89
+ this.on('stop:error', (ctx) => {
90
+ this.status = status_last;
82
91
  });
92
+ // 销毁
83
93
  this.on('destroy:before', (ctx) => {
94
+ status_last = this.status;
84
95
  this.status = 'destroying';
85
96
  });
86
97
  this.on('destroy:check', (ctx) => {
87
- if (this.status !== 'stopped') {
98
+ if (status_last !== 'stopped') {
99
+ status_last = this.status;
88
100
  ctx.error = new Error('销毁前必须先停止');
89
101
  }
90
102
  });
91
- this.on('destroy:after', (ctx) => {
103
+ this.on('destroy:success', (ctx) => {
92
104
  this.status = 'destroyed';
93
105
  });
106
+ this.on('destroy:error', (ctx) => {
107
+ this.status = status_last;
108
+ });
94
109
  };
95
110
 
96
111
  /**
@@ -149,8 +164,8 @@ Base.prototype.destroy = async function () {
149
164
  * 重启
150
165
  */
151
166
  Base.prototype.restart = async function () {
152
- await this.stop();
153
- await this.start();
167
+ await this.do('stop');
168
+ await this.do('start');
154
169
  };
155
170
 
156
171
  /**
@@ -195,43 +210,57 @@ Base.prototype.do = async function (method, ...args) {
195
210
 
196
211
  try {
197
212
  await this._doBeforeProcess(method, ctx);
198
- if (ctx.error || ctx.cancelled) {
213
+ if (ctx.cancelled) {
199
214
  return ctx.result;
200
215
  }
201
216
 
202
217
  await this._doExecuteMethod(method, ctx);
218
+
219
+ // 如果执行成功,进行成功处理
220
+ if (!ctx.error) {
221
+ await this._doSuccessProcess(method, ctx);
222
+ }
223
+
224
+ return ctx.result;
203
225
  } catch (error) {
204
226
  ctx.error = error;
205
227
  this.log('error', `事件驱动执行异常 [${method}]`, error);
228
+
229
+ // 执行错误处理
230
+ await this._doErrorProcess(method, ctx);
231
+
232
+ // 重新抛出错误,让上层能够捕获
233
+ throw error;
234
+ } finally {
235
+ // 无论成功失败,都要执行后处理
236
+ await this._doAfterProcess(method, ctx);
206
237
  }
207
-
208
- await this._doAfterProcess(method, ctx);
209
-
210
- return ctx.result;
211
238
  };
212
239
 
240
+ /**
241
+ * 前处理阶段
242
+ * @param {string} method 方法名称
243
+ * @param {object} ctx 上下文对象
244
+ * @private
245
+ */
213
246
  Base.prototype._doBeforeProcess = async function (method, ctx) {
214
- try {
215
- await this.emitWait(method + ':before', ctx);
216
- } catch (error) {
217
- this.log('error', `前置处理失败 [${method}:before]`, error);
218
- ctx.error = error;
219
- }
247
+ await this.emitWait(method + ':before', ctx);
220
248
  };
221
249
 
250
+ /**
251
+ * 执行方法
252
+ * @param {string} method 方法名称
253
+ * @param {object} ctx 上下文对象
254
+ * @private
255
+ */
222
256
  Base.prototype._doExecuteMethod = async function (method, ctx) {
223
- try {
224
- await this._doCheckPhase(method, ctx);
225
- if (ctx.error) return;
257
+ await this._doCheckPhase(method, ctx);
258
+ if (ctx.error) return;
226
259
 
227
- await this._doMainMethod(method, ctx);
228
- if (ctx.error) return;
260
+ await this._doMainMethod(method, ctx);
261
+ if (ctx.error) return;
229
262
 
230
- await this._doRenderPhase(method, ctx);
231
- } catch (error) {
232
- ctx.error = error;
233
- this.log('error', `执行阶段异常 [${method}]`, error);
234
- }
263
+ await this._doRenderPhase(method, ctx);
235
264
  };
236
265
 
237
266
  /**
@@ -240,62 +269,74 @@ Base.prototype._doExecuteMethod = async function (method, ctx) {
240
269
  * @param {object} ctx 上下文对象
241
270
  */
242
271
  Base.prototype._doCheckPhase = async function (method, ctx) {
243
- let check_result;
244
- try {
245
- check_result = await this.emitRace(method + ':check', ctx);
246
- } catch (error) {
247
- this.log('error', `检查阶段失败 [${method}:check]`, error);
248
- ctx.error = error;
249
- return;
250
- }
272
+ let ret = await this.emitRace(method + ':check', ctx);
251
273
 
252
- if (check_result) {
253
- if (check_result.status === 'rejected') {
254
- ctx.error = check_result.error;
255
- } else if (check_result.status === 'fulfilled' && check_result.result) {
256
- ctx.result = check_result.result;
274
+ if (ret) {
275
+ if (ret.status === 'rejected') {
276
+ ctx.error = ret.error;
277
+ } else if (ret.status === 'fulfilled' && ret.result) {
278
+ ctx.result = ret.result;
257
279
  }
258
280
  }
259
281
  };
260
282
 
283
+ /**
284
+ * 主方法执行
285
+ * @param {string} method 方法名称
286
+ * @param {object} ctx 上下文对象
287
+ * @private
288
+ */
261
289
  Base.prototype._doMainMethod = async function (method, ctx) {
262
290
  if (!ctx.result) {
263
- try {
264
- ctx.result = await this[method](...ctx.params);
265
- } catch (error) {
266
- ctx.error = error;
267
- this.log('error', `主方法执行失败 [${method}]`, error);
268
- }
291
+ ctx.result = await this[method](...ctx.params);
269
292
  }
270
293
  };
271
294
 
295
+ /**
296
+ * 渲染阶段
297
+ * @param {string} method 方法名称
298
+ * @param {object} ctx 上下文对象
299
+ * @private
300
+ */
272
301
  Base.prototype._doRenderPhase = async function (method, ctx) {
273
302
  if (ctx.result && !ctx.error) {
274
- try {
275
- let result = await this.emitWaterfall(method + ':render', ctx.result, ctx);
276
- if (result) {
277
- ctx.result = result;
278
- }
279
- } catch (error) {
280
- this.log('error', `渲染阶段失败 [${method}:render]`, error);
303
+ let result = await this.emitWaterfall(method + ':render', ctx.result, ctx);
304
+ if (result) {
305
+ ctx.result = result;
281
306
  }
282
307
  }
283
308
  };
284
309
 
310
+ /**
311
+ * 成功处理阶段
312
+ * @param {string} method 方法名称
313
+ * @param {object} ctx 上下文对象
314
+ * @private
315
+ */
316
+ Base.prototype._doSuccessProcess = async function (method, ctx) {
317
+ await this.emitWait(method + ':success', ctx);
318
+ };
319
+
320
+ /**
321
+ * 后处理阶段
322
+ * @param {string} method 方法名称
323
+ * @param {object} ctx 上下文对象
324
+ * @private
325
+ */
285
326
  Base.prototype._doAfterProcess = async function (method, ctx) {
286
- if (ctx.error) {
287
- try {
288
- await this.emitAsync(method + ':error', ctx);
289
- this.log('error', `执行方法${method}出错:`, ctx.error);
290
- } catch (error) {
291
- this.log('error', `错误处理失败 [${method}:error]`, error);
292
- }
293
- }
327
+ // 异步触发after事件,不等待执行完成
328
+ this.emitAsync(method + ':after', ctx);
329
+ };
294
330
 
295
- try {
296
- await this.emitWait(method + ':after', ctx);
297
- } catch (error) {
298
- this.log('error', `后置处理失败 [${method}:after]`, error);
331
+ /**
332
+ * 错误处理
333
+ * @param {string} method 方法名称
334
+ * @param {object} ctx 上下文对象
335
+ */
336
+ Base.prototype._doErrorProcess = async function (method, ctx) {
337
+ if (ctx.error) {
338
+ await this.emitAsync(method + ':error', ctx);
339
+ this.log('error', `执行方法${method}出错:`, ctx.error);
299
340
  }
300
341
  };
301
342
 
@@ -378,6 +419,16 @@ Base.prototype.run = async function (...args) {
378
419
  return await this.do('main', ...args);
379
420
  };
380
421
 
422
+ /**
423
+ * 执行方法
424
+ * @param {string} method 方法名称
425
+ * @param {...any} args 参数列表
426
+ * @returns
427
+ */
428
+ Base.prototype.exec = async function (method, ...args) {
429
+ return await this.do(method, ...args);
430
+ };
431
+
381
432
  /**
382
433
  * 执行指令(主要)
383
434
  * @param {string} command 指令
@@ -415,6 +466,11 @@ Base.prototype.cmd = async function (command, ...args) {
415
466
  }
416
467
  };
417
468
 
469
+ /**
470
+ * 解析指令
471
+ * @param {object} ctx 上下文对象
472
+ * @private
473
+ */
418
474
  Base.prototype._cmdParseCommand = function (ctx) {
419
475
  try {
420
476
  ctx.cmds = ctx.command.split('.');
@@ -430,6 +486,11 @@ Base.prototype._cmdParseCommand = function (ctx) {
430
486
  }
431
487
  };
432
488
 
489
+ /**
490
+ * 遍历指令路径
491
+ * @param {object} ctx 上下文对象
492
+ * @private
493
+ */
433
494
  Base.prototype._cmdTraversePath = async function (ctx) {
434
495
  for (let index = 0; index < ctx.cmds.length; index++) {
435
496
  const key = ctx.cmds[index];
@@ -463,6 +524,14 @@ Base.prototype._cmdTraversePath = async function (ctx) {
463
524
  ctx.result = ctx.obj;
464
525
  };
465
526
 
527
+ /**
528
+ * 处理指令对象类型
529
+ * @param {object} ctx 上下文对象
530
+ * @param {string} key 当前键名
531
+ * @param {boolean} is_last 是否为最后一个键名
532
+ * @returns {boolean} 是否停止遍历
533
+ * @private
534
+ */
466
535
  Base.prototype._cmdHandleType = async function (ctx, key, is_last) {
467
536
  const type = typeof ctx.obj;
468
537
 
@@ -478,6 +547,13 @@ Base.prototype._cmdHandleType = async function (ctx, key, is_last) {
478
547
  return false;
479
548
  };
480
549
 
550
+ /**
551
+ * 处理指令对象类型:函数
552
+ * @param {object} ctx 上下文对象
553
+ * @param {boolean} is_last 是否为最后一个键名
554
+ * @returns {boolean} 是否停止遍历
555
+ * @private
556
+ */
481
557
  Base.prototype._cmdHandleFunction = async function (ctx, is_last) {
482
558
  if (typeof ctx.obj !== 'function') {
483
559
  this.log('error', `指令指向的对象不是函数 [${ctx.command}]`);
@@ -501,6 +577,13 @@ Base.prototype._cmdHandleFunction = async function (ctx, is_last) {
501
577
  return false;
502
578
  };
503
579
 
580
+ /**
581
+ * 处理指令对象类型:数组
582
+ * @param {object} ctx 上下文对象
583
+ * @param {boolean} is_last 是否为最后一个键名
584
+ * @returns {boolean} 是否停止遍历
585
+ * @private
586
+ */
504
587
  Base.prototype._cmdHandleArray = function (ctx, is_last) {
505
588
  if (is_last) {
506
589
  ctx.result = ctx.obj;
@@ -513,6 +596,13 @@ Base.prototype._cmdHandleArray = function (ctx, is_last) {
513
596
  return true;
514
597
  };
515
598
 
599
+ /**
600
+ * 处理指令对象类型:原始值
601
+ * @param {object} ctx 上下文对象
602
+ * @param {boolean} is_last 是否为最后一个键名
603
+ * @returns {boolean} 是否停止遍历
604
+ * @private
605
+ */
516
606
  Base.prototype._cmdHandlePrimitive = function (ctx, is_last) {
517
607
  if (is_last) {
518
608
  ctx.result = ctx.obj;
@@ -550,6 +640,11 @@ Base.prototype.help = async function (...args) {
550
640
  }
551
641
  };
552
642
 
643
+ /**
644
+ * 处理帮助参数
645
+ * @param {object} ctx 上下文对象
646
+ * @private
647
+ */
553
648
  Base.prototype._helpProcessArgs = function (ctx) {
554
649
  if (ctx.args.length > 0) {
555
650
  ctx.param = ctx.args[0];
@@ -561,6 +656,11 @@ Base.prototype._helpProcessArgs = function (ctx) {
561
656
  }
562
657
  };
563
658
 
659
+ /**
660
+ * 处理帮助内容
661
+ * @param {object} ctx 上下文对象
662
+ * @private
663
+ */
564
664
  Base.prototype._helpProcessContent = async function (ctx) {
565
665
  if (ctx.param !== null) {
566
666
  await this._helpWithParam(ctx);
@@ -569,6 +669,11 @@ Base.prototype._helpProcessContent = async function (ctx) {
569
669
  }
570
670
  };
571
671
 
672
+ /**
673
+ * 处理帮助参数:有参数
674
+ * @param {object} ctx 上下文对象
675
+ * @private
676
+ */
572
677
  Base.prototype._helpWithParam = async function (ctx) {
573
678
  if (this.helper) {
574
679
  await this._helpUsingHelper(ctx);
@@ -577,6 +682,11 @@ Base.prototype._helpWithParam = async function (ctx) {
577
682
  }
578
683
  };
579
684
 
685
+ /**
686
+ * 处理帮助参数:无参数
687
+ * @param {object} ctx 上下文对象
688
+ * @private
689
+ */
580
690
  Base.prototype._helpUsingHelper = async function (ctx) {
581
691
  try {
582
692
  let hp = this._helpGetHelperValue(ctx.param);
@@ -596,6 +706,12 @@ Base.prototype._helpUsingHelper = async function (ctx) {
596
706
  }
597
707
  };
598
708
 
709
+ /**
710
+ * 获取帮助属性值
711
+ * @param {string} param 参数名
712
+ * @returns {object} 帮助属性值
713
+ * @private
714
+ */
599
715
  Base.prototype._helpGetHelperValue = function (param) {
600
716
  if (!param) {
601
717
  return this.helper;
@@ -609,6 +725,12 @@ Base.prototype._helpGetHelperValue = function (param) {
609
725
  return this.helper;
610
726
  };
611
727
 
728
+ /**
729
+ * 处理帮助数组
730
+ * @param {object} array 数组对象
731
+ * @returns {string} 处理后的数组字符串
732
+ * @private
733
+ */
612
734
  Base.prototype._helpProcessArray = function (array) {
613
735
  let result = '';
614
736
 
@@ -624,6 +746,12 @@ Base.prototype._helpProcessArray = function (array) {
624
746
  return result;
625
747
  };
626
748
 
749
+ /**
750
+ * 处理帮助对象
751
+ * @param {object} obj 对象对象
752
+ * @returns {string} 处理后的对象字符串
753
+ * @private
754
+ */
627
755
  Base.prototype._helpProcessObject = function (obj) {
628
756
  let result = '';
629
757
 
@@ -646,6 +774,11 @@ Base.prototype._helpProcessObject = function (obj) {
646
774
  return result;
647
775
  };
648
776
 
777
+ /**
778
+ * 处理帮助参数:无参数
779
+ * @param {object} ctx 上下文对象
780
+ * @private
781
+ */
649
782
  Base.prototype._helpUsingObject = async function (ctx) {
650
783
  try {
651
784
  if (!ctx.param || typeof ctx.param !== 'string') {
@@ -661,6 +794,12 @@ Base.prototype._helpUsingObject = async function (ctx) {
661
794
  }
662
795
  };
663
796
 
797
+ /**
798
+ * 导航帮助路径
799
+ * @param {string} path 路径字符串
800
+ * @returns {object} 目标对象
801
+ * @private
802
+ */
664
803
  Base.prototype._helpNavigatePath = function (path) {
665
804
  const keys = path.split('.');
666
805
  let obj = this;
@@ -684,6 +823,12 @@ Base.prototype._helpNavigatePath = function (path) {
684
823
  return obj;
685
824
  };
686
825
 
826
+ /**
827
+ * 格式化帮助结果
828
+ * @param {object} target 目标对象
829
+ * @returns {string} 格式化后的结果字符串
830
+ * @private
831
+ */
687
832
  Base.prototype._helpFormatResult = function (target) {
688
833
  if (typeof target === 'function') {
689
834
  try {
@@ -706,6 +851,11 @@ Base.prototype._helpFormatResult = function (target) {
706
851
  }
707
852
  };
708
853
 
854
+ /**
855
+ * 处理帮助参数:无参数
856
+ * @param {object} ctx 上下文对象
857
+ * @private
858
+ */
709
859
  Base.prototype._helpWithoutParam = async function (ctx) {
710
860
  try {
711
861
  ctx.result = this._helpProcessObject(this);