util.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. const formatRegExp = /%[sdj%]/g;
  2. export let warning = () => {
  3. };
  4. export function format(...args) {
  5. let i = 1;
  6. const f = args[0];
  7. const len = args.length;
  8. if (typeof f === 'function') {
  9. return f.apply(null, args.slice(1));
  10. }
  11. if (typeof f === 'string') {
  12. let str = String(f).replace(formatRegExp, (x) => {
  13. if (x === '%%') {
  14. return '%';
  15. }
  16. if (i >= len) {
  17. return x;
  18. }
  19. switch (x) {
  20. case '%s':
  21. return String(args[i++]);
  22. case '%d':
  23. return Number(args[i++]);
  24. case '%j':
  25. try {
  26. return JSON.stringify(args[i++]);
  27. } catch (_) {
  28. return '[Circular]';
  29. }
  30. break;
  31. default:
  32. return x;
  33. }
  34. });
  35. for (let arg = args[i]; i < len; arg = args[++i]) {
  36. str += ` ${arg}`;
  37. }
  38. return str;
  39. }
  40. return f;
  41. }
  42. function isNativeStringType(type) {
  43. return type === 'string' ||
  44. type === 'url' ||
  45. type === 'hex' ||
  46. type === 'email' ||
  47. type === 'pattern';
  48. }
  49. export function isEmptyValue(value, type) {
  50. if (value === undefined || value === null) {
  51. return true;
  52. }
  53. if (type === 'array' && Array.isArray(value) && !value.length) {
  54. return true;
  55. }
  56. if (isNativeStringType(type) && typeof value === 'string' && !value) {
  57. return true;
  58. }
  59. return false;
  60. }
  61. export function isEmptyObject(obj) {
  62. return Object.keys(obj).length === 0;
  63. }
  64. function asyncParallelArray(arr, func, callback) {
  65. const results = [];
  66. let total = 0;
  67. const arrLength = arr.length;
  68. function count(errors) {
  69. results.push.apply(results, errors);
  70. total++;
  71. if (total === arrLength) {
  72. callback(results);
  73. }
  74. }
  75. arr.forEach((a) => {
  76. func(a, count);
  77. });
  78. }
  79. function asyncSerialArray(arr, func, callback) {
  80. let index = 0;
  81. const arrLength = arr.length;
  82. function next(errors) {
  83. if (errors && errors.length) {
  84. callback(errors);
  85. return;
  86. }
  87. const original = index;
  88. index = index + 1;
  89. if (original < arrLength) {
  90. func(arr[original], next);
  91. } else {
  92. callback([]);
  93. }
  94. }
  95. next([]);
  96. }
  97. function flattenObjArr(objArr) {
  98. const ret = [];
  99. Object.keys(objArr).forEach((k) => {
  100. ret.push.apply(ret, objArr[k]);
  101. });
  102. return ret;
  103. }
  104. export function asyncMap(objArr, option, func, callback) {
  105. if (option.first) {
  106. const flattenArr = flattenObjArr(objArr);
  107. return asyncSerialArray(flattenArr, func, callback);
  108. }
  109. let firstFields = option.firstFields || [];
  110. if (firstFields === true) {
  111. firstFields = Object.keys(objArr);
  112. }
  113. const objArrKeys = Object.keys(objArr);
  114. const objArrLength = objArrKeys.length;
  115. let total = 0;
  116. const results = [];
  117. const next = (errors) => {
  118. results.push.apply(results, errors);
  119. total++;
  120. if (total === objArrLength) {
  121. callback(results);
  122. }
  123. };
  124. objArrKeys.forEach((key) => {
  125. const arr = objArr[key];
  126. if (firstFields.indexOf(key) !== -1) {
  127. asyncSerialArray(arr, func, next);
  128. } else {
  129. asyncParallelArray(arr, func, next);
  130. }
  131. });
  132. }
  133. export function complementError(rule) {
  134. return (oe) => {
  135. if (oe && oe.message) {
  136. oe.field = oe.field || rule.fullField;
  137. return oe;
  138. }
  139. return {
  140. message: oe,
  141. field: oe.field || rule.fullField,
  142. };
  143. };
  144. }
  145. export function deepMerge(target, source) {
  146. if (source) {
  147. for (const s in source) {
  148. if (source.hasOwnProperty(s)) {
  149. const value = source[s];
  150. if (typeof value === 'object' && typeof target[s] === 'object') {
  151. target[s] = {
  152. ...target[s],
  153. ...value,
  154. };
  155. } else {
  156. target[s] = value;
  157. }
  158. }
  159. }
  160. }
  161. return target;
  162. }