vue-asyncx 1.5.0 → 1.5.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/README.md CHANGED
@@ -1,40 +1,64 @@
1
1
  ## 特性
2
2
 
3
- - 异步函数样板代码减少50%
4
- - 异步函数相关的函数、变量命名风格统一
5
- - 异步函数调用有序
6
- - 良好的 ts 提示支持
7
- - 单元测试覆盖率 100%
3
+ - 效率+:异步相关样板代码减少50%
4
+ - 效率+:自动处理异步操作的乱序响应
5
+ - 可读+:异步操作命名指向明确、风格统一
6
+ - 可读+:易于写出符合“干净架构”理念的函数
7
+ - 质量+:全 TS 支持 + 100% 单元测试
8
8
 
9
- ## 开始
10
-
11
- ### 安装
9
+ ## 安装
12
10
 
13
11
  ```console
14
12
  pnpm i vue-asyncx
15
13
  ```
16
14
 
17
- ### 使用
15
+ ## 使用
16
+
17
+ ### useAsync 异步函数
18
18
 
19
- #### useAsync 异步函数
19
+ 当需要执行一个异步函数,可以将要执行的异步函数传入 `useAsync` 中,得到
20
+
21
+ - 一个异步函数的包裹函数
22
+ - 一个记录异步函数执行 `loading` 响应式数据
23
+ - 等等
20
24
 
21
25
  ```ts
22
- import { submitOrder } from '@/api'
23
26
  import { useAsync } from 'vue-asyncx'
24
27
 
25
- /**
26
- * 调用 useAsync('submit', ...),
27
- * submit、submitLoading 自动提示
28
- */
29
28
  const {
30
- submit,
31
- submitLoading
32
- } = useAsync('submit', (params: any) => submitOrder(params))
29
+ method,
30
+ methodLoading,
31
+ } = useAsync(async (a: number, b: number) => a + b)
33
32
 
34
- submit({ content: 'Hello World!' })
33
+ method(1, 1).then(total => console.log(total))
35
34
  ```
36
35
 
37
- #### useAsyncData 异步数据
36
+ 如果不喜欢默认解构出来的 `method` 与 `methodLoading`,除了解构赋值的重命名,你还可以直接:
37
+
38
+ ```ts
39
+ import { useAsync } from 'vue-asyncx'
40
+
41
+ const {
42
+ sum,
43
+ sumLoading
44
+ } = useAsync('sum', async (a: number, b: number) => a + b)
45
+
46
+ sum(1, 1).then(total => console.log(total))
47
+ ```
48
+
49
+ 当你将 `sum` 字符串传入 `useAsync`,结果属性自动替换为 `sum` 和 `sumLoading`,并且,**解构附带 ts 提示**,在结果对象内输入 `s`,相关内容会自动提示。
50
+
51
+ 同时,解构出的 `sum` TS 类型由传入的函数推导出,二者 TS 类型一致。
52
+
53
+ 想象一下在多人合作的大型项目中,通过这种方式约束命名:不同开发人员可以自然地将相同模式的变量名关联在一起,互相理解代码、review 内容变得更简单。
54
+
55
+ ### useAsyncData 异步数据
56
+
57
+ 除了异步函数,另一个常见场景是异步数据。
58
+
59
+ 假设你在开发一个用户详情页,页面通过 `user` 数据渲染,`user` 数据通过 `getUserById` 的 api 获取。
60
+
61
+ 显然,`user` 是一个异步数据,通过 `useAsyncData`,你可以很容易处理这些内容:
38
62
 
39
63
  ```ts
40
64
  import { getUserById } from '@/api'
@@ -50,3 +74,306 @@ const {
50
74
  queryUser
51
75
  } = useAsyncData('user', () => getUserById('1'), { immediate: true })
52
76
  ```
77
+
78
+ 代码编写流程与思路流程高度一致:
79
+ - 数据命名:页面需要使用异步数据 user => `useAsyncData('user', `
80
+ - 数据获取:user 数据来自 getUserById 接口 => `useAsyncData('user', () => getUserById('1')`
81
+ - 触发获取:进入页面后需要立即获取 user 数据 `useAsyncData('user', () => getUserById('1'), { immediate: true })`
82
+
83
+ ok,写完上述,页面所需的 `user` 各种相关数据、函数立即出现,想用什么解构什么:
84
+
85
+ - `user` 响应式变量自动定义并声明
86
+ - 获取 `user` 的函数被自动命名为 `queryUser`
87
+ - 调用 `queryUser` 时的加载状态自动关联到 `queryUserLoading`
88
+
89
+ 只需要在 TS 的提示下,按需解构出页面所需的内容
90
+
91
+ > `useAsyncData` 底层使用 `useAsync`,即 `useAsync` 的所有能力 `useAsyncData` 都具备。
92
+ > 除 `useAsync` 的能力外,`useAsyncData` 额外支持了一些与数据相关的能力。
93
+ > 二者区别:
94
+ > `useAsync` 关注异步函数,不关注需要长久保留结果值。例如 `submit`、`confirm` 等操作
95
+ > `useAsyncData` 则关注异步数据,异步函数则是数据的获取方式
96
+
97
+ ### immediate 与 watch
98
+
99
+ 注意到上面例子里的 `useAsyncData` 使用了 `immediate` 配置,效果是立即调用 `queryUser`
100
+
101
+ 这个配置来自 vue `watch`,除了 `immediate` 外,**`useAsync` 和 `useAsyncData`** 完整支持了 vue watch 的各种配置
102
+ - 通过 `options.watch` 配置 watch source
103
+ - 通过 `options.watchOptions` 配置 watch 的其它 options
104
+
105
+ 比如常见的通过 props 传递参数,props 参数改变,触发异步数据改变:
106
+
107
+ ```js
108
+ const {
109
+ user,
110
+ queryUserLoading,
111
+ queryUser
112
+ } = useAsyncData('user', () => getUserById(props.id), {
113
+ watch: () => props.id, // 此处用 props 举例,支持所有 vue watch source 的用法
114
+ immediate: true,
115
+ watchOptions: {
116
+ once: true // 此处用 once 举例,支持所有 vue watch options 内的配置
117
+ // 这里也可以配置 immediate,与上一层的 immediate 效果一致,优先级更高
118
+ }
119
+ })
120
+ ```
121
+
122
+ 实际上即使不配置 `options.watch`,配置 `options.immediate = true` 后内部也是通过 watch 机制触发的立即调用
123
+
124
+ 默认情况下,由 watch 触发的调用不会传递任何参数。watch 的 handler 相当于:`() => queryUser()`。但在 vue 中,watch 的 handler 可以接收新、旧数据以及 `onCleanup`
125
+
126
+ `useAsync` 和 `useAsyncData` 可以通过配置 `options.watchOptions.handlerCreator` 来自定义 watch handler:
127
+
128
+ ```js
129
+ const {
130
+ user,
131
+ queryUserLoading,
132
+ queryUser
133
+ } = useAsyncData('user', (id) => getUserById(id), {
134
+ watch: () => props.id,
135
+ immediate: true,
136
+ watchOptions: {
137
+ // fn 等价于 queryUser
138
+ handlerCreator(fn) {
139
+ // handlerCreator 需要返回 watch 的 handler
140
+ return (newId, oldId, onCleanup) => {
141
+ // handler 用法与 vue watch handler 一致,可以排除某些非法调用
142
+ if (!newId) return
143
+ fn(newId)
144
+ }
145
+ },
146
+ }
147
+ })
148
+ ```
149
+
150
+ ### 调用报错与参数
151
+
152
+ 除了 `loading`,`useAsync` 与 `useAsyncData` 还支持记录调用的 `error` 与 `arguments`,默认状态下,它们的命名是:
153
+
154
+ ```js
155
+ const {
156
+ methodError,
157
+ methodArguments,
158
+ } = useAsync(() => {})
159
+
160
+ const {
161
+ queryDataError,
162
+ queryDataArguments
163
+ } = useAsyncData(() => {})
164
+ ```
165
+
166
+ 与之前例子一致,当自定义命名时,结果随之改变:
167
+
168
+ ```js
169
+ const {
170
+ confirmError,
171
+ confirmArguments,
172
+ } = useAsync('confirm', () => {})
173
+
174
+ const {
175
+ queryUserError,
176
+ queryUserArguments
177
+ } = useAsyncData('user', () => {})
178
+ ```
179
+
180
+ `error`
181
+ - **最后一次**调用 fn,**且**调用结果失败
182
+ - 记录异步 fn 的 reject 内容
183
+ - 记录同步 fn 的 throw 内容
184
+ - **新一次**调用开始后,`error` 自动置空
185
+
186
+ `arguments`
187
+ - 与 `loading` 一致,调用开始时记录本次调用传入的参数
188
+ - 调用结果出现后,`arguments` 自动置空
189
+
190
+ ### 异步函数乱序响应
191
+
192
+ ```js
193
+ // 使用 useAsync,没有 user 变量
194
+ const {
195
+ queryUser,
196
+ queryUserLoading,
197
+ } = useAsync('queryUser', () => {})
198
+
199
+ // 或者,使用 useAsyncData
200
+ const {
201
+ user,
202
+ queryUser,
203
+ queryUserLoading
204
+ } = useAsyncData('user', () => {})
205
+ ```
206
+
207
+ `queryUser` 是个异步函数,由于异步操作时间不定,多次调用情况下会出现乱序响应,考虑下列的时间线顺序:
208
+
209
+ - **首次调用** `queryUser`,记做 `queryUser1`
210
+ - `queryUser1` 未结束,**再次调用** `queryUser`,记做 `queryUser2`
211
+ - `queryUser2` 先结束
212
+ - `queryUser1` 后结束
213
+
214
+ 即:**依次调用 `queryUser1` 和 `queryUser2`,但 `queryUser2` 先于 `queryUser1` 结束**。这种场景很常见,专门处理很麻烦。
215
+
216
+ 而使用 `useAsync` 和 `useAsyncData`,你无需再考虑这类问题,方法会自动帮你处理。
217
+
218
+ 以上述例子举例:
219
+
220
+ - `queryUser1` 开始时,`queryUserLoading.value` 为 `true`
221
+ - **`queryUser2` 结束时**,`queryUserLoading.value` 为 `false`
222
+
223
+ 对于 `useAsyncData`,`queryUser` 对应的 `user` 数据:
224
+
225
+ - `user.value` 将始终以 `queryUser2` 的结果为准(取**最晚的调用**产生的结果)
226
+ - 即使 `queryUser1` 产生结果的时间更晚,但 `queryUser1` 的结果不会更新到 `user.value` 上
227
+ - `queryUser1` 的结果会被自动舍弃,因为这是一个“过期的”数据
228
+
229
+ > 另一种处理重复调用的方式是不允许在上次调用未结束时再次调用
230
+ >
231
+ > 由于 `useAsync` 和 `useAsyncData` 提供了响应式的 `loading`,对于常用组件库,向按钮传入 `loading` 状态或在 `disabled` 属性中添加 `loading` 判断即可轻松避免
232
+ >
233
+ > 此处讨论的是因数据源变动导致异步数据需要刷新的场景,比如 `userId` 短时间从 `1` 切换到 `2`,`user` 数据需要做对应刷新
234
+
235
+ ### 数据过期
236
+
237
+ > 过期数据标注是 `useAsyncData` 独有功能
238
+
239
+ ```js
240
+ const {
241
+ user,
242
+ queryUser,
243
+ queryUserError,
244
+ userExpired
245
+ } = useAsyncData('user', () => {})
246
+ ```
247
+
248
+ 假设是以下时间线:
249
+
250
+ - 首次调用 `queryUser`,记做 `queryUser1`
251
+ - `queryUser1` 未结束,再次调用 `queryUser`,记做 `queryUser2`
252
+ - `queryUser2` 先结束,**但发生报错**
253
+ - `queryUser1` 后结束
254
+
255
+ 此时:
256
+ - `queryUser2` 的错误会被记录到 `queryUserError.value` 上
257
+ - `queryUser1` 的结果**会被更新到** `user.value` 上
258
+ - `userExpired.value` 会被设置为 `true`,表明当前的 `user.value` 是个过期数据(因为 `user.value` 来自`queryUser1`,而最新的结果是 `queryUser2` 的报错)
259
+
260
+ > 大多数情况下,无需考虑 `userExpired.value` 的问题,因为它只会在 `queryUserError.value` 出现时出现,优先处理 `queryUserError.value` 往往是更好的做法
261
+
262
+ > `userExpired.value` 为 `true` 后,直到下次调用更新 `user.value` 前,`userExpired.value` 将一直保持 `true` 状态。
263
+ > 原因:`userExpired.value` 为 `true` 后,虽然再次调用了 `queryUser`,但在 `user.value` 再次更新前,`user.value` 当前的值仍是“过期的”珊瑚橘
264
+
265
+ > 由于乱序的问题,如果在 `queryUser1` 时使用了 `.then(res => ...)`,`res` 的值是 `queryUser1` 的结果,与 `user.value` 不一致,这是符合预期的。
266
+
267
+ ### 异步数据的中途获取与更新
268
+
269
+ > 异步数据中途获取与更新是 `useAsyncData` 独有功能
270
+
271
+ 在某些场景下,我们希望异步数据可以在异步获取过程中更新,无需等到获取过程完全结束。
272
+
273
+ 可以通过 `options.enhanceFirstArgument = true` 支持这种需求。
274
+
275
+ ```js
276
+ import { unFirstArgumentEnhanced, useAsyncData } from 'vue-asyncx'
277
+
278
+ const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
279
+
280
+ const {
281
+ progress,
282
+ queryProgress
283
+ } = useAsyncData('progress', async (init?: number) => {
284
+ const { getData, updateData } = unFirstArgumentEnhanced(init)
285
+ init = unFirstArgumentEnhanced(init).firstArgument
286
+ updateData(init || 0)
287
+ await wait(100)
288
+ updateData(50)
289
+ await wait(100)
290
+ return 100
291
+ }, {
292
+ enhanceFirstArgument: true
293
+ })
294
+
295
+ queryProgress(10)
296
+ ```
297
+
298
+ 在上述代码的最后一行调用 `queryProgress(10)` 后:
299
+ - `progress.value` 会立即更新为 `10`
300
+ - 100ms 后 `progress.value` 更新为 `50`
301
+ - 再过 100ms 后,`progress.value` 更新为 `100`,本次调用结束
302
+
303
+ 注意到在传入 `useAsyncData` 的 `fn` 内,有
304
+
305
+ ```js
306
+ const { getData, updateData } = unFirstArgumentEnhanced(init)
307
+ init = unFirstArgumentEnhanced(init).firstArgument
308
+ ```
309
+
310
+ 原理:
311
+
312
+ 当 `options.enhanceFirstArgument = true` 后
313
+ - `fn` 的首个参数 `init` 便被拓展为 `FirstArgumentEnhanced` 类型。
314
+ - 实际调用 `queryProgress(10)` 时传入的 `10` 在 `fn` 内部通过 `init` 接收时变成了 `{ getData, updateData, firstArgument }`,`10` 被赋在了 `init.firstArgument` 上
315
+ - `unFirstArgumentEnhanced(init)` 先解构出 `getData` 和 `updateData`,再将 `init` 重新赋值为传入的 `10`
316
+
317
+ > 也就是在 `fn` 内部可以直接通过
318
+ > `const { getData, updateData, firstArgument } = init`
319
+ > 但是这样写需要自行处理 TS 类型问题,因此提供了 `unFirstArgumentEnhanced` 辅助函数。
320
+
321
+ 只需要记住
322
+
323
+ - 可以像以往一般正常定义 `fn`、调用 `queryProgress`
324
+ - 在 `fn` 内部实现的最上方,加上上述的两行代码,余下即可正常使用
325
+
326
+ 如果 `fn` 本身不接收参数,那么可以改成普通函数,通过 `arguments[0]` 传递:
327
+
328
+ ```js
329
+ const {
330
+ progress,
331
+ queryProgress
332
+ } = useAsyncData('progress', async function () {
333
+ const { getData, updateData } = unFirstArgumentEnhanced(arguments[0])
334
+ updateData(0)
335
+ await wait(100)
336
+ updateData(50)
337
+ await wait(100)
338
+ return 100
339
+ }, {
340
+ enhanceFirstArgument: true
341
+ })
342
+
343
+ queryProgress()
344
+ ```
345
+
346
+ 在某些情况下,需要区分 `queryProgress()` 与 `queryProgress(undefined)`,可以通过:
347
+
348
+ ```js
349
+ const firstArgumentEnhanced = unFirstArgumentEnhanced(arguments[0])
350
+ const undefinedOrEmpty = 'firstArgument' in firstArgumentEnhanced
351
+ ```
352
+
353
+
354
+
355
+ - `firstArgumentEnhanced` 存在 `firstArgument` 属性时,是 `queryProgress(undefined)`
356
+ - `firstArgumentEnhanced` 不存在 `firstArgument` 属性时,是 `queryProgress()`
357
+
358
+ 本块 api 设计思考过程见
359
+
360
+ - [rfc1-async-data-update](./docs/rfc1-async-data-update.md)
361
+
362
+ 其它
363
+
364
+ - `getData` 总是返回最新的数据
365
+ - `setData` 不保证设置成功(比如发生了乱序响应的情况)
366
+ - 接上,`setData` 支持处理乱序响应,一旦有新的调用触发 `setData`,旧调用的 `setData` 操作会被忽略
367
+
368
+ ## 理念
369
+
370
+ 在“干净架构”里,函数拆分的原则是:一个函数应该做且只做一件事
371
+
372
+ - 对于传入 `useAsyncData` 的函数 `fn` 而言,唯一需要关注的就是如何设置 `data` 的值
373
+ - 对于在 `data` 值初始化后需要干的其它事情,可以在 `useAsyncData` **外部** 通过 vue 的 watch data 去触发
374
+ - 对于 `useAsyncData` 整体而言,我们将与 `data` 值相关的代码都聚集在了一起
375
+ - loading、error、expired、arguments 等数据与 data 或 fn 紧密相关
376
+ - watch 设置了 fn 的调用时机,即初始化 data 的时机
377
+
378
+ 通过上面的约定,很容易写出“干净”的函数与高内聚的代码块,提高代码可读性
379
+
@@ -5,7 +5,7 @@ import { WatchSource } from 'vue';
5
5
 
6
6
  declare type FirstArgumentEnhanced<T = any, D = any> = {
7
7
  [FLAG_FIRST_ARGUMENT_ENHANCED]: true;
8
- firstArgument: T;
8
+ firstArgument?: T;
9
9
  getData: () => D;
10
10
  updateData: (v: D) => void;
11
11
  };
@@ -14,7 +14,7 @@ declare const FLAG_FIRST_ARGUMENT_ENHANCED = "__va_fae";
14
14
 
15
15
  declare type StringDefaultWhenEmpty<S extends string, D extends string> = S extends '' ? D : S;
16
16
 
17
- export declare function unFirstArgumentEnhanced<Arg = any, Data = any>(arg: Arg): FirstArgumentEnhanced<Arg, Data>;
17
+ export declare function unFirstArgumentEnhanced<Arg = any, Data = any>(arg: Arg): Arg extends undefined ? FirstArgumentEnhanced<Arg, Data> : Required<FirstArgumentEnhanced<Arg, Data>>;
18
18
 
19
19
  declare function useAsync<Fn extends (...args: any) => any>(fn: Fn, options?: UseAsyncOptions<Fn>): UseAsyncResult<Fn, 'method'>;
20
20
 
@@ -1,47 +1,47 @@
1
1
  var L = Object.defineProperty, O = Object.defineProperties;
2
2
  var b = Object.getOwnPropertyDescriptors;
3
3
  var F = Object.getOwnPropertySymbols;
4
- var _ = Object.prototype.hasOwnProperty, T = Object.prototype.propertyIsEnumerable;
5
- var U = (e, n, t) => n in e ? L(e, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[n] = t, B = (e, n) => {
6
- for (var t in n || (n = {}))
7
- _.call(n, t) && U(e, t, n[t]);
4
+ var B = Object.prototype.hasOwnProperty, $ = Object.prototype.propertyIsEnumerable;
5
+ var T = (e, n, r) => n in e ? L(e, n, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[n] = r, w = (e, n) => {
6
+ for (var r in n || (n = {}))
7
+ B.call(n, r) && T(e, r, n[r]);
8
8
  if (F)
9
- for (var t of F(n))
10
- T.call(n, t) && U(e, t, n[t]);
9
+ for (var r of F(n))
10
+ $.call(n, r) && T(e, r, n[r]);
11
11
  return e;
12
- }, $ = (e, n) => O(e, b(n));
13
- var w = (e, n) => {
14
- var t = {};
12
+ }, C = (e, n) => O(e, b(n));
13
+ var U = (e, n) => {
14
+ var r = {};
15
15
  for (var a in e)
16
- _.call(e, a) && n.indexOf(a) < 0 && (t[a] = e[a]);
16
+ B.call(e, a) && n.indexOf(a) < 0 && (r[a] = e[a]);
17
17
  if (e != null && F)
18
18
  for (var a of F(e))
19
- n.indexOf(a) < 0 && T.call(e, a) && (t[a] = e[a]);
20
- return t;
19
+ n.indexOf(a) < 0 && $.call(e, a) && (r[a] = e[a]);
20
+ return r;
21
21
  };
22
22
  import { ref as E, watch as x, computed as N } from "vue";
23
23
  function j(...e) {
24
24
  var v;
25
25
  if (!Array.isArray(e) || !e.length) throw TypeError("参数错误:未传递");
26
- const { name: n, fn: t, options: a } = typeof e[0] == "function" ? { name: "method", fn: e[0], options: e[1] } : { name: e[0] || "method", fn: e[1], options: e[2] };
26
+ const { name: n, fn: r, options: a } = typeof e[0] == "function" ? { name: "method", fn: e[0], options: e[1] } : { name: e[0] || "method", fn: e[1], options: e[2] };
27
27
  if (typeof n != "string") throw TypeError("参数错误:name");
28
- if (typeof t != "function") throw TypeError("参数错误:fn");
28
+ if (typeof r != "function") throw TypeError("参数错误:fn");
29
29
  const p = E(!1), m = E(), s = E(), u = { called: 0, finished: 0 };
30
30
  function y(...h) {
31
- const d = ++u.called, A = (r) => {
32
- s.value = void 0, p.value = !0, m.value = r;
33
- }, c = (r, { scene: i, sn: o }) => {
34
- o > u.finished && (u.finished = o), u.called === u.finished && (i === "error" && (s.value = r), p.value = !1, m.value = void 0);
31
+ const d = ++u.called, A = (t) => {
32
+ s.value = void 0, p.value = !0, m.value = t;
33
+ }, c = (t, { scene: i, sn: o }) => {
34
+ o > u.finished && (u.finished = o), u.called === u.finished && (i === "error" && (s.value = t), p.value = !1, m.value = void 0);
35
35
  };
36
36
  A(h);
37
37
  try {
38
- const r = t(...h);
39
- return r instanceof Promise ? r.then(
38
+ const t = r(...h);
39
+ return t instanceof Promise ? t.then(
40
40
  () => c(void 0, { scene: "normal", sn: d }),
41
41
  (i) => c(i, { scene: "error", sn: d })
42
- ) : c(void 0, { scene: "normal", sn: d }), r;
43
- } catch (r) {
44
- throw c(r, { scene: "error", sn: d }), r;
42
+ ) : c(void 0, { scene: "normal", sn: d }), t;
43
+ } catch (t) {
44
+ throw c(t, { scene: "error", sn: d }), t;
45
45
  }
46
46
  }
47
47
  if (a) {
@@ -50,7 +50,7 @@ function j(...e) {
50
50
  {},
51
51
  "immediate" in a ? { immediate: a.immediate } : {},
52
52
  (v = a.watchOptions) != null ? v : {}
53
- ), { handlerCreator: d } = l, A = w(l, ["handlerCreator"]), { watch: c } = a, i = (() => {
53
+ ), { handlerCreator: d } = l, A = U(l, ["handlerCreator"]), { watch: c } = a, i = (() => {
54
54
  const o = () => y();
55
55
  if (typeof d != "function") return o;
56
56
  try {
@@ -71,16 +71,16 @@ function j(...e) {
71
71
  }
72
72
  function G(e) {
73
73
  if (!e) return "";
74
- const n = e[0], t = e.slice(1);
75
- return n.toUpperCase() + t;
74
+ const n = e[0], r = e.slice(1);
75
+ return n.toUpperCase() + r;
76
76
  }
77
77
  const D = "__va_fae";
78
78
  function z(...e) {
79
79
  if (!Array.isArray(e) || !e.length) throw TypeError("参数错误:未传递");
80
- const { name: n, fn: t, options: a } = typeof e[0] == "function" ? { name: "data", fn: e[0], options: e[1] } : { name: e[0] || "data", fn: e[1], options: e[2] };
80
+ const { name: n, fn: r, options: a } = typeof e[0] == "function" ? { name: "data", fn: e[0], options: e[1] } : { name: e[0] || "data", fn: e[1], options: e[2] };
81
81
  if (typeof n != "string") throw TypeError("参数错误:name");
82
- if (typeof t != "function") throw TypeError("参数错误:fn");
83
- const c = a || {}, { enhanceFirstArgument: p } = c, m = w(c, ["enhanceFirstArgument"]), s = E({
82
+ if (typeof r != "function") throw TypeError("参数错误:fn");
83
+ const c = a || {}, { enhanceFirstArgument: p } = c, m = U(c, ["enhanceFirstArgument"]), s = E({
84
84
  // 调用序号(即:fn 第 called 次调用)
85
85
  called: 0,
86
86
  // 完成序号(即:fn 第 finished 次调用完成)
@@ -90,30 +90,30 @@ function z(...e) {
90
90
  // 数据完成更新序号(即:data 数据由第 dataUpdateByFinished 次调用完成后更新)
91
91
  dataUpdateByFinished: 0
92
92
  }), u = E(), y = N(() => !(s.value.dataUpdateByFinished >= s.value.finished || s.value.dataUpdateByCalled > s.value.finished));
93
- function v(r, { sn: i, scene: o }) {
94
- i < s.value.dataUpdateByCalled || (u.value = r, s.value.dataUpdateByCalled = i, o === "finish" && (s.value.dataUpdateByFinished = i));
93
+ function v(t, { sn: i, scene: o }) {
94
+ i < s.value.dataUpdateByCalled || (u.value = t, s.value.dataUpdateByCalled = i, o === "finish" && (s.value.dataUpdateByFinished = i));
95
95
  }
96
- function l(r, { scene: i, sn: o }) {
97
- i === "normal" && v(r, { sn: o, scene: "finish" }), o > s.value.finished && (s.value.finished = o);
96
+ function l(t, { scene: i, sn: o }) {
97
+ i === "normal" && v(t, { sn: o, scene: "finish" }), o > s.value.finished && (s.value.finished = o);
98
98
  }
99
- function h(r, {
99
+ function h(t, {
100
100
  enhanceFirstArgument: i,
101
101
  sn: o
102
102
  }) {
103
- if (!i) return r;
104
- const [f, ...H] = r;
105
- return [{
106
- [D]: !0,
107
- firstArgument: f,
103
+ if (!i) return t;
104
+ const [f, ...H] = t;
105
+ return [C(w({
106
+ [D]: !0
107
+ }, t.length ? { firstArgument: f } : {}), {
108
108
  getData: () => u.value,
109
- updateData: (C) => (v(C, { sn: o, scene: "update" }), C)
110
- }, ...H];
109
+ updateData: (_) => (v(_, { sn: o, scene: "update" }), _)
110
+ }), ...H];
111
111
  }
112
- function d(...r) {
112
+ function d(...t) {
113
113
  const i = ++s.value.called;
114
- r = h(r, { enhanceFirstArgument: p, sn: i });
114
+ t = h(t, { enhanceFirstArgument: p, sn: i });
115
115
  try {
116
- const o = t(...r);
116
+ const o = r(...t);
117
117
  return o instanceof Promise ? o.then(
118
118
  // promise 正常结束
119
119
  (f) => l(f, { scene: "normal", sn: i }),
@@ -125,7 +125,7 @@ function z(...e) {
125
125
  }
126
126
  }
127
127
  const A = j(`query${G(n)}`, d, m);
128
- return $(B({}, A), {
128
+ return C(w({}, A), {
129
129
  [n]: u,
130
130
  [`${n}Expired`]: y
131
131
  });
@@ -1 +1 @@
1
- (function(e,n){typeof exports=="object"&&typeof module!="undefined"?n(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],n):(e=typeof globalThis!="undefined"?globalThis:e||self,n(e.VueAsyncx={},e.Vue))})(this,function(e,n){"use strict";var P=Object.defineProperty,q=Object.defineProperties;var x=Object.getOwnPropertyDescriptors;var C=Object.getOwnPropertySymbols;var D=Object.prototype.hasOwnProperty,O=Object.prototype.propertyIsEnumerable;var b=(e,n,a)=>n in e?P(e,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[n]=a,$=(e,n)=>{for(var a in n||(n={}))D.call(n,a)&&b(e,a,n[a]);if(C)for(var a of C(n))O.call(n,a)&&b(e,a,n[a]);return e},j=(e,n)=>q(e,x(n));var U=(e,n)=>{var a={};for(var c in e)D.call(e,c)&&n.indexOf(c)<0&&(a[c]=e[c]);if(e!=null&&C)for(var c of C(e))n.indexOf(c)<0&&O.call(e,c)&&(a[c]=e[c]);return a};function a(...t){var w;if(!Array.isArray(t)||!t.length)throw TypeError("参数错误:未传递");const{name:f,fn:p,options:y}=typeof t[0]=="function"?{name:"method",fn:t[0],options:t[1]}:{name:t[0]||"method",fn:t[1],options:t[2]};if(typeof f!="string")throw TypeError("参数错误:name");if(typeof p!="function")throw TypeError("参数错误:fn");const v=n.ref(!1),E=n.ref(),s=n.ref(),l={called:0,finished:0};function F(...A){const h=++l.called,T=i=>{s.value=void 0,v.value=!0,E.value=i},u=(i,{scene:o,sn:r})=>{r>l.finished&&(l.finished=r),l.called===l.finished&&(o==="error"&&(s.value=i),v.value=!1,E.value=void 0)};T(A);try{const i=p(...A);return i instanceof Promise?i.then(()=>u(void 0,{scene:"normal",sn:h}),o=>u(o,{scene:"error",sn:h})):u(void 0,{scene:"normal",sn:h}),i}catch(i){throw u(i,{scene:"error",sn:h}),i}}if(y){const A=()=>{},m=Object.assign({},"immediate"in y?{immediate:y.immediate}:{},(w=y.watchOptions)!=null?w:{}),{handlerCreator:h}=m,T=U(m,["handlerCreator"]),{watch:u}=y,o=(()=>{const r=()=>F();if(typeof h!="function")return r;try{const d=h(F);return typeof d=="function"?d:r}catch(d){return r}})();n.watch(u!=null?u:A,o,T)}return{[f]:F,[`${f}Loading`]:v,[`${f}Arguments`]:E,[`${f}Error`]:s}}function c(t){if(!t)return"";const f=t[0],p=t.slice(1);return f.toUpperCase()+p}const _="__va_fae";function H(...t){if(!Array.isArray(t)||!t.length)throw TypeError("参数错误:未传递");const{name:f,fn:p,options:y}=typeof t[0]=="function"?{name:"data",fn:t[0],options:t[1]}:{name:t[0]||"data",fn:t[1],options:t[2]};if(typeof f!="string")throw TypeError("参数错误:name");if(typeof p!="function")throw TypeError("参数错误:fn");const u=y||{},{enhanceFirstArgument:v}=u,E=U(u,["enhanceFirstArgument"]),s=n.ref({called:0,finished:0,dataUpdateByCalled:0,dataUpdateByFinished:0}),l=n.ref(),F=n.computed(()=>!(s.value.dataUpdateByFinished>=s.value.finished||s.value.dataUpdateByCalled>s.value.finished));function w(i,{sn:o,scene:r}){o<s.value.dataUpdateByCalled||(l.value=i,s.value.dataUpdateByCalled=o,r==="finish"&&(s.value.dataUpdateByFinished=o))}function m(i,{scene:o,sn:r}){o==="normal"&&w(i,{sn:r,scene:"finish"}),r>s.value.finished&&(s.value.finished=r)}function A(i,{enhanceFirstArgument:o,sn:r}){if(!o)return i;const[d,...N]=i;return[{[_]:!0,firstArgument:d,getData:()=>l.value,updateData:B=>(w(B,{sn:r,scene:"update"}),B)},...N]}function h(...i){const o=++s.value.called;i=A(i,{enhanceFirstArgument:v,sn:o});try{const r=p(...i);return r instanceof Promise?r.then(d=>m(d,{scene:"normal",sn:o}),d=>m(d,{scene:"error",sn:o})):m(r,{scene:"normal",sn:o}),r}catch(r){throw m(r,{scene:"error",sn:o}),r}}const T=a(`query${c(f)}`,h,E);return j($({},T),{[f]:l,[`${f}Expired`]:F})}function L(t){if(typeof t!="object"||!t||!t[_])throw Error("请配置 options.enhanceFirstArgument = true");return t}e.unFirstArgumentEnhanced=L,e.useAsync=a,e.useAsyncData=H,e.useAsyncFunction=a,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
1
+ (function(e,n){typeof exports=="object"&&typeof module!="undefined"?n(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],n):(e=typeof globalThis!="undefined"?globalThis:e||self,n(e.VueAsyncx={},e.Vue))})(this,function(e,n){"use strict";var P=Object.defineProperty,q=Object.defineProperties;var x=Object.getOwnPropertyDescriptors;var C=Object.getOwnPropertySymbols;var $=Object.prototype.hasOwnProperty,j=Object.prototype.propertyIsEnumerable;var O=(e,n,a)=>n in e?P(e,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[n]=a,U=(e,n)=>{for(var a in n||(n={}))$.call(n,a)&&O(e,a,n[a]);if(C)for(var a of C(n))j.call(n,a)&&O(e,a,n[a]);return e},_=(e,n)=>q(e,x(n));var B=(e,n)=>{var a={};for(var c in e)$.call(e,c)&&n.indexOf(c)<0&&(a[c]=e[c]);if(e!=null&&C)for(var c of C(e))n.indexOf(c)<0&&j.call(e,c)&&(a[c]=e[c]);return a};function a(...t){var w;if(!Array.isArray(t)||!t.length)throw TypeError("参数错误:未传递");const{name:f,fn:p,options:y}=typeof t[0]=="function"?{name:"method",fn:t[0],options:t[1]}:{name:t[0]||"method",fn:t[1],options:t[2]};if(typeof f!="string")throw TypeError("参数错误:name");if(typeof p!="function")throw TypeError("参数错误:fn");const v=n.ref(!1),E=n.ref(),s=n.ref(),l={called:0,finished:0};function F(...A){const h=++l.called,T=i=>{s.value=void 0,v.value=!0,E.value=i},u=(i,{scene:o,sn:r})=>{r>l.finished&&(l.finished=r),l.called===l.finished&&(o==="error"&&(s.value=i),v.value=!1,E.value=void 0)};T(A);try{const i=p(...A);return i instanceof Promise?i.then(()=>u(void 0,{scene:"normal",sn:h}),o=>u(o,{scene:"error",sn:h})):u(void 0,{scene:"normal",sn:h}),i}catch(i){throw u(i,{scene:"error",sn:h}),i}}if(y){const A=()=>{},m=Object.assign({},"immediate"in y?{immediate:y.immediate}:{},(w=y.watchOptions)!=null?w:{}),{handlerCreator:h}=m,T=B(m,["handlerCreator"]),{watch:u}=y,o=(()=>{const r=()=>F();if(typeof h!="function")return r;try{const d=h(F);return typeof d=="function"?d:r}catch(d){return r}})();n.watch(u!=null?u:A,o,T)}return{[f]:F,[`${f}Loading`]:v,[`${f}Arguments`]:E,[`${f}Error`]:s}}function c(t){if(!t)return"";const f=t[0],p=t.slice(1);return f.toUpperCase()+p}const b="__va_fae";function H(...t){if(!Array.isArray(t)||!t.length)throw TypeError("参数错误:未传递");const{name:f,fn:p,options:y}=typeof t[0]=="function"?{name:"data",fn:t[0],options:t[1]}:{name:t[0]||"data",fn:t[1],options:t[2]};if(typeof f!="string")throw TypeError("参数错误:name");if(typeof p!="function")throw TypeError("参数错误:fn");const u=y||{},{enhanceFirstArgument:v}=u,E=B(u,["enhanceFirstArgument"]),s=n.ref({called:0,finished:0,dataUpdateByCalled:0,dataUpdateByFinished:0}),l=n.ref(),F=n.computed(()=>!(s.value.dataUpdateByFinished>=s.value.finished||s.value.dataUpdateByCalled>s.value.finished));function w(i,{sn:o,scene:r}){o<s.value.dataUpdateByCalled||(l.value=i,s.value.dataUpdateByCalled=o,r==="finish"&&(s.value.dataUpdateByFinished=o))}function m(i,{scene:o,sn:r}){o==="normal"&&w(i,{sn:r,scene:"finish"}),r>s.value.finished&&(s.value.finished=r)}function A(i,{enhanceFirstArgument:o,sn:r}){if(!o)return i;const[d,...N]=i;return[_(U({[b]:!0},i.length?{firstArgument:d}:{}),{getData:()=>l.value,updateData:D=>(w(D,{sn:r,scene:"update"}),D)}),...N]}function h(...i){const o=++s.value.called;i=A(i,{enhanceFirstArgument:v,sn:o});try{const r=p(...i);return r instanceof Promise?r.then(d=>m(d,{scene:"normal",sn:o}),d=>m(d,{scene:"error",sn:o})):m(r,{scene:"normal",sn:o}),r}catch(r){throw m(r,{scene:"error",sn:o}),r}}const T=a(`query${c(f)}`,h,E);return _(U({},T),{[f]:l,[`${f}Expired`]:F})}function L(t){if(typeof t!="object"||!t||!t[b])throw Error("请配置 options.enhanceFirstArgument = true");return t}e.unFirstArgumentEnhanced=L,e.useAsync=a,e.useAsyncData=H,e.useAsyncFunction=a,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-asyncx",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "types": "dist/vue-asyncx.d.ts",
@@ -44,6 +44,7 @@
44
44
  "build": "vite build",
45
45
  "test:unit": "vitest",
46
46
  "test:unit:coverage": "vitest run --coverage",
47
- "test": "pnpm run test:unit"
47
+ "test": "pnpm run test:unit",
48
+ "prepublish": "pnpm run build"
48
49
  }
49
50
  }