foreslash 0.2.2 → 0.2.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Change Log
2
2
 
3
+ ## Version 0.2.3 - 2025-03-28
4
+
5
+ Unstable version
6
+
7
+ - Feat 🥥 Functions added: `defer`
8
+ - Fix 🥕 Bug fixed: `debounce` doesn't apply the last callee's arguments
9
+ - Other fixes and improvements
10
+
11
+ 不稳定版本
12
+
13
+ - 功能 🥥 添加函数: `defer`
14
+ - 修复 🥕 缺陷修复: `debounce` 没有传入最后一次获取的参数
15
+ - 其他修复与优化
16
+
3
17
  ## Version 0.2.2 - 2025-03-18
4
18
 
5
19
  Unstable version
package/lib/index.cmn.cjs CHANGED
@@ -67,11 +67,37 @@ function remove(arr, ...item) {
67
67
  return res;
68
68
  }
69
69
 
70
- function sleep(time = 1000) {
71
- return new Promise((res) => {
72
- setTimeout(res, time);
73
- });
74
- }
70
+ /******************************************************************************
71
+ Copyright (c) Microsoft Corporation.
72
+
73
+ Permission to use, copy, modify, and/or distribute this software for any
74
+ purpose with or without fee is hereby granted.
75
+
76
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
77
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
78
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
79
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
80
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
81
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
82
+ PERFORMANCE OF THIS SOFTWARE.
83
+ ***************************************************************************** */
84
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
85
+
86
+
87
+ function __awaiter(thisArg, _arguments, P, generator) {
88
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
89
+ return new (P || (P = Promise))(function (resolve, reject) {
90
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
91
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
92
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
93
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
94
+ });
95
+ }
96
+
97
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
98
+ var e = new Error(message);
99
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
100
+ };
75
101
 
76
102
  const isArray = Array.isArray;
77
103
 
@@ -171,7 +197,7 @@ function isNumber(value) {
171
197
  }
172
198
 
173
199
  function isPrimitive(value) {
174
- return value == null || (typeof value !== 'object' && typeof value !== 'function');
200
+ return value === undefined || value === null || (typeof value !== 'object' && typeof value !== 'function');
175
201
  }
176
202
 
177
203
  function isPromise(value) {
@@ -292,6 +318,45 @@ function tryit(fn) {
292
318
  };
293
319
  }
294
320
 
321
+ function defer(asyncFunction, options) {
322
+ return __awaiter(this, void 0, void 0, function* () {
323
+ const queue = [];
324
+ const { rethrow = false } = options || {};
325
+ const defaultOption = { rethrow };
326
+ const cleanUp = (fn, options) => {
327
+ queue.push({ fn, opt: Object.assign(defaultOption, options) });
328
+ return queue.length - 1;
329
+ };
330
+ const cancelCleanUp = (fnOrIndex) => {
331
+ if (isInteger(fnOrIndex) && fnOrIndex > -1)
332
+ queue[fnOrIndex] = null;
333
+ else if (isFunction(fnOrIndex)) {
334
+ const i = queue.findIndex((item) => item && item.fn === fnOrIndex);
335
+ if (i > -1)
336
+ queue[i] = null;
337
+ }
338
+ };
339
+ const [err, res] = yield tryit(asyncFunction)(cleanUp, cancelCleanUp);
340
+ for (const item of queue) {
341
+ if (!item)
342
+ continue;
343
+ const { fn, opt } = item;
344
+ const [cleanUpErr] = yield tryit(fn)(err);
345
+ if (cleanUpErr && opt.rethrow)
346
+ throw cleanUpErr;
347
+ }
348
+ if (err)
349
+ throw err;
350
+ return res;
351
+ });
352
+ }
353
+
354
+ function sleep(time = 1000) {
355
+ return new Promise((res) => {
356
+ setTimeout(res, time);
357
+ });
358
+ }
359
+
295
360
  const noop = function noop() { };
296
361
 
297
362
  function withResolvers(PromiseLike = Promise) {
@@ -1321,9 +1386,10 @@ function _curryMore(fn) {
1321
1386
  }
1322
1387
 
1323
1388
  function _throttle(fn, delay, options) {
1324
- var _a, _b;
1389
+ var _a, _b, _c;
1325
1390
  const trailing = (_a = options === null || options === void 0 ? void 0 : options.trailing) !== null && _a !== void 0 ? _a : false;
1326
- const leading = (_b = options === null || options === void 0 ? void 0 : options.leading) !== null && _b !== void 0 ? _b : true;
1391
+ const trailingRunLast = (_b = options === null || options === void 0 ? void 0 : options.trailingRunLast) !== null && _b !== void 0 ? _b : true;
1392
+ const leading = (_c = options === null || options === void 0 ? void 0 : options.leading) !== null && _c !== void 0 ? _c : true;
1327
1393
  let timer = null;
1328
1394
  let lastTime = 0;
1329
1395
  const clearTimer = () => {
@@ -1343,6 +1409,9 @@ function _throttle(fn, delay, options) {
1343
1409
  lastTime = now;
1344
1410
  clearTimer();
1345
1411
  }
1412
+ if (timeGap < 0 && trailing && trailingRunLast && timer) {
1413
+ clearTimer();
1414
+ }
1346
1415
  if (timeGap >= 0 && leading) {
1347
1416
  fn.apply(this, args);
1348
1417
  }
@@ -1360,7 +1429,7 @@ function debounce(fn, delay, options) {
1360
1429
  if (!isNumber(delay) || !isFinite(delay) || delay <= 0) {
1361
1430
  throw new Error('Invalid delay parameter');
1362
1431
  }
1363
- return _throttle(fn, delay, Object.assign({ trailing: true, leading: false }, options));
1432
+ return _throttle(fn, delay, Object.assign({ trailing: true, leading: false, trailingRunLast: true }, options));
1364
1433
  }
1365
1434
 
1366
1435
  function _cloneArray(obj, map, cloner, ...args) {
@@ -1648,6 +1717,7 @@ exports.compose = compose;
1648
1717
  exports.curry = _curryMore;
1649
1718
  exports.debounce = debounce;
1650
1719
  exports.deepClone = deepClone;
1720
+ exports.defer = defer;
1651
1721
  exports.fastClone = fastClone;
1652
1722
  exports.getAcceptableExtByMIME = getAcceptableExtByMIME;
1653
1723
  exports.getAcceptableMIMEByExt = getAcceptableMIMEByExt;
package/lib/index.d.ts CHANGED
@@ -77,6 +77,45 @@ declare function range<T = number>(start: number, end: number, options?: RangeOp
77
77
  */
78
78
  declare function remove<T>(arr: ArrayLike<T>, ...item: (T | ((val: T) => unknown))[]): T[];
79
79
 
80
+ type DeferCallbackFunction = (error?: Error) => unknown;
81
+ type DeferOption = {
82
+ rethrow: boolean;
83
+ };
84
+ /**
85
+ * 在传入的函数执行完毕后(或是抛出异常后), 执行*延迟操作*\
86
+ * 使用场景一般是处理“副作用”, 类似 `try {} finally {}` 结构但是更加灵活
87
+ * - 执行*延迟操作*的时机是函数执行完毕后(或是抛出异常后), 同时 `defer` 返回的 `Promise` 并未结束
88
+ * - 这个设计是防止*延迟操作*与后续逻辑产生干扰
89
+ * - `defer` 返回的 `Promise` 会根据传入的函数是否正常处理/抛出异常而变化
90
+ * - 传入的函数正常处理, 结果为 `1`, 那么 `defer` 将返回 `Promise {<fulfilled>: 1}`
91
+ * - 传入的函数抛出异常, 内容为 `2`, 那么 `defer` 将返回 `Promise {<rejected>: 2}`
92
+ *
93
+ * *延迟操作*时抛出的错误不会正常抛出
94
+ * - 如果希望执行*延迟操作*时正常抛错, 您可以配置 `options.rethrow = true`
95
+ * @param asyncFunction 需要在执行完毕后做额外处理函数
96
+ * @param options.rethrow 执行*延迟操作*时是否正常抛错, 默认不抛错
97
+ * @returns 一个 `Promise` 会根据传入的函数是否正常处理/抛出异常而变化
98
+ * @example
99
+ * ```js
100
+ * // 一般用途
101
+ * defer((cleanUp) => {
102
+ * cleanUp(() => console.log(2))
103
+ * cleanUp(() => console.log(3))
104
+ * console.log(1)
105
+ * }) // 依次输出 1 2 3
106
+ * // 可以动态取消计划好的延迟操作
107
+ * defer((cleanUp, cancelCleanUp) => {
108
+ * const cleanUpId = cleanUp(() => console.log(123)) // 会返回一个数字作为 id
109
+ * cleanUp(() => console.log(5))
110
+ * cleanUp(() => console.log(6))
111
+ * console.log(4)
112
+ * cancelCleanUp(cleanUpId) // 可以用于取消指定的延迟操作
113
+ * }) // 依次输出 4 5 6
114
+ * ```
115
+ * @version 0.2.3
116
+ */
117
+ declare function defer<T>(asyncFunction: (cleanUp: (fn: DeferCallbackFunction) => number, cancelCleanUp: (fnOrIndex: DeferCallbackFunction | number) => void) => T | Promise<T>, options?: Partial<DeferOption>): Promise<T>;
118
+
80
119
  /**
81
120
  * 延迟一定时间
82
121
  * @param time 延迟时间, 单位为毫秒(ms), 默认为 `1000` (即 1 秒)
@@ -740,6 +779,7 @@ declare function isWrapperBigInt(value: unknown): value is BigInt;
740
779
  * clamp(15, 0, 10, { default: 6 }) // 6
741
780
  * clamp(-5, 0, 10, { default: 6 }) // 6
742
781
  * ```
782
+ * @version 0.2.2
743
783
  */
744
784
  declare function clamp(num: number, min: number, max: number, options?: {
745
785
  default?: number;
@@ -1320,6 +1360,8 @@ declare function _curryMore<Args extends Array<any>, Res>(fn: (...args: Args) =>
1320
1360
  interface ThrottleOptions {
1321
1361
  /** 节流时触发的最后一次调用是否执行, 默认为否 */
1322
1362
  trailing?: boolean;
1363
+ /** 触发的最后一次调用是否使用最后一次的参数, 默认为是 */
1364
+ trailingRunLast?: boolean;
1323
1365
  /** 第一次触发是否直接执行, 默认为是 */
1324
1366
  leading?: boolean;
1325
1367
  }
@@ -1631,4 +1673,4 @@ declare function throttle<T extends any[]>(fn: (...args: T) => any, delay: numbe
1631
1673
  reset: () => void;
1632
1674
  };
1633
1675
 
1634
- export { type CloneOptions, type CustomCloner, type RangeOptions, type TypedArray, _, acceptableFileName, acceptableFileType, camelCase, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, clamp, compose, _curryMore as curry, debounce, deepClone, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isNil, isNull, isNumber, isObject, isPlaceholder, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uuidNil, uuidV4, withResolvers };
1676
+ export { type CloneOptions, type CustomCloner, type RangeOptions, type TypedArray, _, acceptableFileName, acceptableFileType, camelCase, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, clamp, compose, _curryMore as curry, debounce, deepClone, defer, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isNil, isNull, isNumber, isObject, isPlaceholder, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uuidNil, uuidV4, withResolvers };
package/lib/index.mjs CHANGED
@@ -65,11 +65,37 @@ function remove(arr, ...item) {
65
65
  return res;
66
66
  }
67
67
 
68
- function sleep(time = 1000) {
69
- return new Promise((res) => {
70
- setTimeout(res, time);
71
- });
72
- }
68
+ /******************************************************************************
69
+ Copyright (c) Microsoft Corporation.
70
+
71
+ Permission to use, copy, modify, and/or distribute this software for any
72
+ purpose with or without fee is hereby granted.
73
+
74
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
75
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
76
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
77
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
78
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
79
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
80
+ PERFORMANCE OF THIS SOFTWARE.
81
+ ***************************************************************************** */
82
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
83
+
84
+
85
+ function __awaiter(thisArg, _arguments, P, generator) {
86
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
87
+ return new (P || (P = Promise))(function (resolve, reject) {
88
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
89
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
90
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
91
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
92
+ });
93
+ }
94
+
95
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
96
+ var e = new Error(message);
97
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
98
+ };
73
99
 
74
100
  const isArray = Array.isArray;
75
101
 
@@ -169,7 +195,7 @@ function isNumber(value) {
169
195
  }
170
196
 
171
197
  function isPrimitive(value) {
172
- return value == null || (typeof value !== 'object' && typeof value !== 'function');
198
+ return value === undefined || value === null || (typeof value !== 'object' && typeof value !== 'function');
173
199
  }
174
200
 
175
201
  function isPromise(value) {
@@ -290,6 +316,45 @@ function tryit(fn) {
290
316
  };
291
317
  }
292
318
 
319
+ function defer(asyncFunction, options) {
320
+ return __awaiter(this, void 0, void 0, function* () {
321
+ const queue = [];
322
+ const { rethrow = false } = options || {};
323
+ const defaultOption = { rethrow };
324
+ const cleanUp = (fn, options) => {
325
+ queue.push({ fn, opt: Object.assign(defaultOption, options) });
326
+ return queue.length - 1;
327
+ };
328
+ const cancelCleanUp = (fnOrIndex) => {
329
+ if (isInteger(fnOrIndex) && fnOrIndex > -1)
330
+ queue[fnOrIndex] = null;
331
+ else if (isFunction(fnOrIndex)) {
332
+ const i = queue.findIndex((item) => item && item.fn === fnOrIndex);
333
+ if (i > -1)
334
+ queue[i] = null;
335
+ }
336
+ };
337
+ const [err, res] = yield tryit(asyncFunction)(cleanUp, cancelCleanUp);
338
+ for (const item of queue) {
339
+ if (!item)
340
+ continue;
341
+ const { fn, opt } = item;
342
+ const [cleanUpErr] = yield tryit(fn)(err);
343
+ if (cleanUpErr && opt.rethrow)
344
+ throw cleanUpErr;
345
+ }
346
+ if (err)
347
+ throw err;
348
+ return res;
349
+ });
350
+ }
351
+
352
+ function sleep(time = 1000) {
353
+ return new Promise((res) => {
354
+ setTimeout(res, time);
355
+ });
356
+ }
357
+
293
358
  const noop = function noop() { };
294
359
 
295
360
  function withResolvers(PromiseLike = Promise) {
@@ -1319,9 +1384,10 @@ function _curryMore(fn) {
1319
1384
  }
1320
1385
 
1321
1386
  function _throttle(fn, delay, options) {
1322
- var _a, _b;
1387
+ var _a, _b, _c;
1323
1388
  const trailing = (_a = options === null || options === void 0 ? void 0 : options.trailing) !== null && _a !== void 0 ? _a : false;
1324
- const leading = (_b = options === null || options === void 0 ? void 0 : options.leading) !== null && _b !== void 0 ? _b : true;
1389
+ const trailingRunLast = (_b = options === null || options === void 0 ? void 0 : options.trailingRunLast) !== null && _b !== void 0 ? _b : true;
1390
+ const leading = (_c = options === null || options === void 0 ? void 0 : options.leading) !== null && _c !== void 0 ? _c : true;
1325
1391
  let timer = null;
1326
1392
  let lastTime = 0;
1327
1393
  const clearTimer = () => {
@@ -1341,6 +1407,9 @@ function _throttle(fn, delay, options) {
1341
1407
  lastTime = now;
1342
1408
  clearTimer();
1343
1409
  }
1410
+ if (timeGap < 0 && trailing && trailingRunLast && timer) {
1411
+ clearTimer();
1412
+ }
1344
1413
  if (timeGap >= 0 && leading) {
1345
1414
  fn.apply(this, args);
1346
1415
  }
@@ -1358,7 +1427,7 @@ function debounce(fn, delay, options) {
1358
1427
  if (!isNumber(delay) || !isFinite(delay) || delay <= 0) {
1359
1428
  throw new Error('Invalid delay parameter');
1360
1429
  }
1361
- return _throttle(fn, delay, Object.assign({ trailing: true, leading: false }, options));
1430
+ return _throttle(fn, delay, Object.assign({ trailing: true, leading: false, trailingRunLast: true }, options));
1362
1431
  }
1363
1432
 
1364
1433
  function _cloneArray(obj, map, cloner, ...args) {
@@ -1632,4 +1701,4 @@ function throttle(fn, delay, options) {
1632
1701
  return _throttle(fn, delay, Object.assign({ trailing: false, leading: true }, options));
1633
1702
  }
1634
1703
 
1635
- export { _, acceptableFileName, acceptableFileType, camelCase, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, clamp, compose, _curryMore as curry, debounce, deepClone, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isNil, isNull, isNumber, isObject, isPlaceholder, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uuidNil, uuidV4, withResolvers };
1704
+ export { _, acceptableFileName, acceptableFileType, camelCase, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, clamp, compose, _curryMore as curry, debounce, deepClone, defer, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isNil, isNull, isNumber, isObject, isPlaceholder, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uuidNil, uuidV4, withResolvers };
package/lib/index.umd.js CHANGED
@@ -71,11 +71,37 @@ See the Mulan PSL v2 for more details.
71
71
  return res;
72
72
  }
73
73
 
74
- function sleep(time = 1000) {
75
- return new Promise((res) => {
76
- setTimeout(res, time);
77
- });
78
- }
74
+ /******************************************************************************
75
+ Copyright (c) Microsoft Corporation.
76
+
77
+ Permission to use, copy, modify, and/or distribute this software for any
78
+ purpose with or without fee is hereby granted.
79
+
80
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
81
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
82
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
83
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
84
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
85
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
86
+ PERFORMANCE OF THIS SOFTWARE.
87
+ ***************************************************************************** */
88
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
89
+
90
+
91
+ function __awaiter(thisArg, _arguments, P, generator) {
92
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
93
+ return new (P || (P = Promise))(function (resolve, reject) {
94
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
95
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
96
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
97
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
98
+ });
99
+ }
100
+
101
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
102
+ var e = new Error(message);
103
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
104
+ };
79
105
 
80
106
  const isArray = Array.isArray;
81
107
 
@@ -175,7 +201,7 @@ See the Mulan PSL v2 for more details.
175
201
  }
176
202
 
177
203
  function isPrimitive(value) {
178
- return value == null || (typeof value !== 'object' && typeof value !== 'function');
204
+ return value === undefined || value === null || (typeof value !== 'object' && typeof value !== 'function');
179
205
  }
180
206
 
181
207
  function isPromise(value) {
@@ -296,6 +322,45 @@ See the Mulan PSL v2 for more details.
296
322
  };
297
323
  }
298
324
 
325
+ function defer(asyncFunction, options) {
326
+ return __awaiter(this, void 0, void 0, function* () {
327
+ const queue = [];
328
+ const { rethrow = false } = options || {};
329
+ const defaultOption = { rethrow };
330
+ const cleanUp = (fn, options) => {
331
+ queue.push({ fn, opt: Object.assign(defaultOption, options) });
332
+ return queue.length - 1;
333
+ };
334
+ const cancelCleanUp = (fnOrIndex) => {
335
+ if (isInteger(fnOrIndex) && fnOrIndex > -1)
336
+ queue[fnOrIndex] = null;
337
+ else if (isFunction(fnOrIndex)) {
338
+ const i = queue.findIndex((item) => item && item.fn === fnOrIndex);
339
+ if (i > -1)
340
+ queue[i] = null;
341
+ }
342
+ };
343
+ const [err, res] = yield tryit(asyncFunction)(cleanUp, cancelCleanUp);
344
+ for (const item of queue) {
345
+ if (!item)
346
+ continue;
347
+ const { fn, opt } = item;
348
+ const [cleanUpErr] = yield tryit(fn)(err);
349
+ if (cleanUpErr && opt.rethrow)
350
+ throw cleanUpErr;
351
+ }
352
+ if (err)
353
+ throw err;
354
+ return res;
355
+ });
356
+ }
357
+
358
+ function sleep(time = 1000) {
359
+ return new Promise((res) => {
360
+ setTimeout(res, time);
361
+ });
362
+ }
363
+
299
364
  const noop = function noop() { };
300
365
 
301
366
  function withResolvers(PromiseLike = Promise) {
@@ -1325,9 +1390,10 @@ See the Mulan PSL v2 for more details.
1325
1390
  }
1326
1391
 
1327
1392
  function _throttle(fn, delay, options) {
1328
- var _a, _b;
1393
+ var _a, _b, _c;
1329
1394
  const trailing = (_a = options === null || options === void 0 ? void 0 : options.trailing) !== null && _a !== void 0 ? _a : false;
1330
- const leading = (_b = options === null || options === void 0 ? void 0 : options.leading) !== null && _b !== void 0 ? _b : true;
1395
+ const trailingRunLast = (_b = options === null || options === void 0 ? void 0 : options.trailingRunLast) !== null && _b !== void 0 ? _b : true;
1396
+ const leading = (_c = options === null || options === void 0 ? void 0 : options.leading) !== null && _c !== void 0 ? _c : true;
1331
1397
  let timer = null;
1332
1398
  let lastTime = 0;
1333
1399
  const clearTimer = () => {
@@ -1347,6 +1413,9 @@ See the Mulan PSL v2 for more details.
1347
1413
  lastTime = now;
1348
1414
  clearTimer();
1349
1415
  }
1416
+ if (timeGap < 0 && trailing && trailingRunLast && timer) {
1417
+ clearTimer();
1418
+ }
1350
1419
  if (timeGap >= 0 && leading) {
1351
1420
  fn.apply(this, args);
1352
1421
  }
@@ -1364,7 +1433,7 @@ See the Mulan PSL v2 for more details.
1364
1433
  if (!isNumber(delay) || !isFinite(delay) || delay <= 0) {
1365
1434
  throw new Error('Invalid delay parameter');
1366
1435
  }
1367
- return _throttle(fn, delay, Object.assign({ trailing: true, leading: false }, options));
1436
+ return _throttle(fn, delay, Object.assign({ trailing: true, leading: false, trailingRunLast: true }, options));
1368
1437
  }
1369
1438
 
1370
1439
  function _cloneArray(obj, map, cloner, ...args) {
@@ -1652,6 +1721,7 @@ See the Mulan PSL v2 for more details.
1652
1721
  exports.curry = _curryMore;
1653
1722
  exports.debounce = debounce;
1654
1723
  exports.deepClone = deepClone;
1724
+ exports.defer = defer;
1655
1725
  exports.fastClone = fastClone;
1656
1726
  exports.getAcceptableExtByMIME = getAcceptableExtByMIME;
1657
1727
  exports.getAcceptableMIMEByExt = getAcceptableMIMEByExt;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreslash",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Foreslash is a Javascript utilities lib which contains plenty of practical functions.",
5
5
  "author": "moushu",
6
6
  "license": "Mulan PSL v2",