1# @arkts.utils (ArkTS Utils)
2
3The Utils module provides a variety of ArkTS utility functions.
4
5> **NOTE**
6>
7> The initial APIs of this module are supported since API version 12. Newly added APIs will be marked with a superscript to indicate their earliest API version.
8
9## Modules to Import
10
11```ts
12import { ArkTSUtils } from '@kit.ArkTS'
13```
14
15## ArkTSUtils.locks
16
17To avoid data races between concurrent instances, the ArkTS common library introduces **AsyncLock**. Passing **AsyncLock** objects by reference across concurrent instances is supported.
18
19ArkTS supports asynchronous operations, and blocking locks are prone to deadlocks. Therefore, only asynchronous locks (non-blocking locks) are used in ArkTS.
20
21The method that uses an asynchronous lock must be marked as **async**, and the caller must use **await** in the call to ensure the correct call sequence. As a result, all outer functions are marked as **async**.
22
23### AsyncLockCallback
24
25type AsyncLockCallback\<T> = () => T | Promise\<T>
26
27A supplementary type alias that represents the callback in all the overloads of [lockAsync](#lockasync).
28
29**Atomic service API**: This API can be used in atomic services since API version 12.
30
31**System capability**: SystemCapability.Utils.Lang
32
33### AsyncLock
34
35A class that implements an asynchronous lock and allows asynchronous operations to be performed under a lock.
36
37#### Attributes
38
39**Atomic service API**: This API can be used in atomic services since API version 12.
40
41**System capability**: SystemCapability.Utils.Lang
42
43| Name| Type  | Readable| Writable| Description      |
44| ---- | ------ | ---- | ---- | ---------- |
45| name | string | Yes  | No  | Name of the lock.|
46
47**Example**
48
49```ts
50// Example 1
51@Sendable
52class A {
53  count_: number = 0;
54  async getCount(): Promise<number> {
55    let lock: ArkTSUtils.locks.AsyncLock = ArkTSUtils.locks.AsyncLock.request("lock_1");
56    return lock.lockAsync(() => {
57      return this.count_;
58    })
59  }
60  async setCount(count: number) {
61    let lock: ArkTSUtils.locks.AsyncLock = ArkTSUtils.locks.AsyncLock.request("lock_1");
62    await lock.lockAsync(() => {
63      this.count_ = count;
64    })
65  }
66}
67
68// Example 2
69@Sendable
70class A {
71  count_: number = 0;
72  lock_: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock();
73  async getCount(): Promise<number> {
74    return this.lock_.lockAsync(() => {
75      return this.count_;
76    })
77  }
78  async setCount(count: number) {
79    await this.lock_.lockAsync(() => {
80      this.count_ = count;
81    })
82  }
83}
84
85@Concurrent
86async function foo(a: A) {
87  await a.setCount(10)
88}
89```
90
91#### constructor
92
93constructor()
94
95Default constructor used to create an asynchronous lock.
96
97**Atomic service API**: This API can be used in atomic services since API version 12.
98
99**System capability**: SystemCapability.Utils.Lang
100
101**Return value**
102
103| Type                   | Description              |
104| ----------------------- | ------------------ |
105| [AsyncLock](#asynclock) | **AsyncLock** instance created.|
106
107**Example**
108
109```ts
110let lock = new ArkTSUtils.locks.AsyncLock();
111```
112
113#### request
114
115static request(name: string): AsyncLock
116
117Finds or creates (if not found) an **AsyncLock** instance with the specified name.
118
119**Atomic service API**: This API can be used in atomic services since API version 12.
120
121**System capability**: SystemCapability.Utils.Lang
122
123**Parameters**
124
125| Name| Type  | Mandatory| Description                            |
126| ---- | ------ | ---- | -------------------------------- |
127| name | string | Yes  | Name of the lock.|
128
129**Return value**
130
131| Type                   | Description                            |
132| ----------------------- | -------------------------------- |
133| [AsyncLock](#asynclock) | **AsyncLock** instance found or created.|
134
135**Example**
136
137```ts
138let lockName = 'isAvailableLock';
139let lock = ArkTSUtils.locks.AsyncLock.request(lockName);
140```
141
142#### query
143
144static query(name: string): AsyncLockState
145
146Queries information about an asynchronous lock.
147
148**Atomic service API**: This API can be used in atomic services since API version 12.
149
150**System capability**: SystemCapability.Utils.Lang
151
152**Parameters**
153
154| Name| Type  | Mandatory| Description      |
155| ---- | ------ | ---- | ---------- |
156| name | string | Yes  | Name of the lock.|
157
158**Return value**
159
160| Type                             | Description                              |
161| --------------------------------- | ---------------------------------- |
162| [AsyncLockState](#asynclockstate) | **AsyncLockState** instance that contains the lock state information.|
163
164**Error codes**
165
166For details about the error codes, see [Utils Error Codes](errorcode-utils.md).
167
168| ID| Error Message     |
169| -------- | ------------- |
170| 10200030 | The lock does not exist. |
171
172**Example**
173
174```ts
175// You have created a lock somewhere else.
176// let lock = ArkTSUtils.locks.AsyncLock.request("queryTestLock");
177let state = ArkTSUtils.locks.AsyncLock.query('queryTestLock');
178if (!state) {
179    throw new Error('Test failed: A valid state is expected, but the obtained state is '+ state);
180}
181let pending: ArkTSUtils.locks.AsyncLockInfo[] = state.pending;
182let held: ArkTSUtils.locks.AsyncLockInfo[] = state.held;
183```
184
185#### queryAll
186
187static queryAll(): AsyncLockState[]
188
189Queries information about all existing asynchronous locks.
190
191**Atomic service API**: This API can be used in atomic services since API version 12.
192
193**System capability**: SystemCapability.Utils.Lang
194
195**Return value**
196
197| Type                               | Description                            |
198| ----------------------------------- | -------------------------------- |
199| [AsyncLockState](#asynclockstate)[] | **AsyncLockState** array that contains the lock state information.|
200
201**Example**
202
203```ts
204let states: ArkTSUtils.locks.AsyncLockState[] = ArkTSUtils.locks.AsyncLock.queryAll();
205if (states.length == 0) {
206    throw new Error ('Test failed: At least one state is expected, but what got is ' + states.length);
207}
208```
209
210#### lockAsync
211
212lockAsync\<T>(callback: AsyncLockCallback\<T>): Promise\<T>
213
214Performs an operation exclusively under a lock. This API acquires the lock, executes the callback, and releases the lock. The callback is executed asynchronously in the same thread where [lockAsync](#lockasync) was called.
215
216**Atomic service API**: This API can be used in atomic services since API version 12.
217
218**System capability**: SystemCapability.Utils.Lang
219
220**Parameters**
221
222| Name    | Type                                   | Mandatory| Description                  |
223| -------- | --------------------------------------- | ---- | ---------------------- |
224| callback | [AsyncLockCallback](#asynclockcallback) | Yes  | Callback to be executed after a lock is acquired.|
225
226**Return value**
227
228| Type       | Description                       |
229| ----------- | --------------------------- |
230| Promise\<T> | Promise that will be resolved after the callback is executed.|
231
232**Error codes**
233
234For details about the error codes, see [Utils Error Codes](errorcode-utils.md).
235
236| ID| Error Message     |
237| -------- | ------------- |
238| 10200030 | The lock does not exist. |
239
240**Example**
241
242```ts
243let lock = new ArkTSUtils.locks.AsyncLock();
244let p1 = lock.lockAsync<void>(() => {
245    // Perform an operation.
246});
247```
248
249#### lockAsync
250
251lockAsync\<T>(callback: AsyncLockCallback\<T>, mode: AsyncLockMode): Promise\<T>
252
253Performs an operation under a lock. This API acquires the lock, executes the callback, and releases the lock. The callback is executed asynchronously in the same thread where [lockAsync](#lockasync) was called.
254
255**Atomic service API**: This API can be used in atomic services since API version 12.
256
257**System capability**: SystemCapability.Utils.Lang
258
259**Parameters**
260
261| Name    | Type                                   | Mandatory| Description                  |
262| -------- | --------------------------------------- | ---- | ---------------------- |
263| callback | [AsyncLockCallback](#asynclockcallback) | Yes  | Callback to be executed after a lock is acquired.|
264| mode     | [AsyncLockMode](#asynclockmode)         | Yes  | Mode of the lock.        |
265
266**Return value**
267
268| Type       | Description                       |
269| ----------- | --------------------------- |
270| Promise\<T> | Promise that will be resolved after the callback is executed.|
271
272**Error codes**
273
274For details about the error codes, see [Utils Error Codes](errorcode-utils.md).
275
276| ID| Error Message     |
277| -------- | ------------- |
278| 10200030 | The lock does not exist. |
279
280**Example**
281
282```ts
283let lock = new ArkTSUtils.locks.AsyncLock();
284let p1 = lock.lockAsync<void>(() => {
285    // Perform an operation.
286}, ArkTSUtils.locks.AsyncLockMode.EXCLUSIVE);
287```
288
289#### lockAsync
290
291lockAsync\<T, U>(callback: AsyncLockCallback\<T>, mode: AsyncLockMode, options: AsyncLockOptions\<U>): Promise\<T | U>
292
293Performs an operation under a lock. This API acquires the lock, executes the callback, and releases the lock. The callback is executed asynchronously in the same thread where [lockAsync](#lockasync) was called. An optional timeout value can be provided in [AsyncLockOptions](#asynclockoptions). If a lock is not acquired before timeout, **lockAsync** returns a projected Promise with a **BusinessError** instance. In this instance, the error message contains information about the locks being held and in the waiting state, as well as possible deadlock warnings.
294
295**Atomic service API**: This API can be used in atomic services since API version 12.
296
297**System capability**: SystemCapability.Utils.Lang
298
299**Parameters**
300
301| Name    | Type                                     | Mandatory| Description                  |
302| -------- | ----------------------------------------- | ---- | ---------------------- |
303| callback | [AsyncLockCallback](#asynclockcallback)   | Yes  | Callback to be executed after a lock is acquired.|
304| mode     | [AsyncLockMode](#asynclockmode)           | Yes  | Mode of the lock.        |
305| options  | [AsyncLockOptions\<U>](#asynclockoptions) | Yes  | Options of the lock.        |
306
307**Return value**
308
309| Type            | Description                                              |
310| ---------------- | -------------------------------------------------- |
311| Promise\<T \| U> | Promise that will be resolved after the callback is executed, or rejected in the case of timeout.|
312
313**Error codes**
314
315For details about the error codes, see [Utils Error Codes](errorcode-utils.md).
316
317| ID| Error Message         |
318| -------- | ----------------- |
319| 10200030 | The lock does not exist.     |
320| 10200031 | Timeout exceeded. |
321
322**Example**
323
324```ts
325let lock = new ArkTSUtils.locks.AsyncLock();
326let options = new ArkTSUtils.locks.AsyncLockOptions<void>();
327options.timeout = 1000;
328let p: Promise<void> = lock.lockAsync<void, void>(
329    () => {
330        // Perform an operation.
331    },
332    ArkTSUtils.locks.AsyncLockMode.EXCLUSIVE,
333    options
334);
335```
336
337### AsyncLockMode
338
339Enumerates the modes of an asynchronous lock.
340
341**Atomic service API**: This API can be used in atomic services since API version 12.
342
343**System capability**: SystemCapability.Utils.Lang
344
345| Name     | Value | Description                                                    |
346| --------- | --- | -------------------------------------------------------- |
347| SHARED    | 1   | Shared lock. An operation can be reentrant in the same thread.|
348| EXCLUSIVE | 2   | Exclusive lock. An operation is performed only when the lock is exclusively acquired.|
349
350### AsyncLockOptions
351
352class AsyncLockOptions\<T>
353
354Class that implements the asynchronous lock options.
355
356**Atomic service API**: This API can be used in atomic services since API version 12.
357
358**System capability**: SystemCapability.Utils.Lang
359
360#### constructor
361
362constructor()
363
364Default constructor used to create an **AsyncLockOptions** instance with the default values for all attributes.
365
366**Atomic service API**: This API can be used in atomic services since API version 12.
367
368**System capability**: SystemCapability.Utils.Lang
369
370**Return value**
371
372| Type                                 | Description                  |
373| ------------------------------------- | ---------------------- |
374| [AsyncLockOptions](#asynclockoptions) | **AsyncLockOptions** instance created.|
375
376**Example**
377
378```ts
379let s: ArkTSUtils.locks.AbortSignal<string> = { aborted: false, reason: 'Aborted' };
380let options = new ArkTSUtils.locks.AsyncLockOptions<string>();
381options.isAvailable = false;
382options.signal = s;
383```
384
385#### Attributes
386
387| Name       | Type                                 | Readable| Writable| Description                                                                                                                     |
388| ----------- | ------------------------------------- | ---- | ---- | ------------------------------------------------------------------------------------------------------------------------- |
389| isAvailable | boolean                               | Yes  | Yes  | Whether the lock is available. If the value is **true**, a lock is granted only when it is not held. If the value is **false**, a lock is granted once it is released. The default value is **false**.|
390| signal      | [AbortSignal\<T>](#abortsignal)\|null | Yes  | Yes  | Signal used to abort an asynchronous operation. If **signal.aborted** is **true**, the lock request is discarded. If **signal.aborted** is **null**, the request is queued normally. The default value is **null**.              |
391| timeout     | number                                | Yes  | Yes  | Timeout interval of the lock request, in milliseconds. If the value is greater than zero and a lock is not acquired before time, [lockAsync](#lockasync) returns a rejected Promise. The default value is **0**.     |
392
393### AsyncLockState
394
395A class used to store information about all lock operations currently performed on an **AsyncLock** instance.
396
397**Atomic service API**: This API can be used in atomic services since API version 12.
398
399**System capability**: SystemCapability.Utils.Lang
400
401#### Attributes
402
403| Name   | Type                             | Readable| Writable| Description            |
404| ------- | --------------------------------- | ---- | ---- | ---------------- |
405| held    | [AsyncLockInfo[]](#asynclockinfo) | Yes  | Yes  | Information about the lock being held.  |
406| pending | [AsyncLockInfo[]](#asynclockinfo) | Yes  | Yes  | Information about the lock in the waiting state.|
407
408### AsyncLockInfo
409
410Describes the information about a lock.
411
412**Atomic service API**: This API can be used in atomic services since API version 12.
413
414**System capability**: SystemCapability.Utils.Lang
415
416#### Attributes
417
418| Name     | Type                           | Readable| Writable| Description                                                     |
419| --------- | ------------------------------- | ---- | ---- | --------------------------------------------------------- |
420| name      | string                          | Yes  | Yes  | Name of the lock.                                               |
421| mode      | [AsyncLockMode](#asynclockmode) | Yes  | Yes  | Mode of the lock.                                               |
422| contextId | number                          | Yes  | Yes  | Context identifier of the caller of [AsyncLockMode](#asynclockmode).|
423
424### AbortSignal
425
426A class that implements a signal used to abort an asynchronous operation. An instance of this class must be accessed in the same thread it creates. Otherwise, undefined behavior occurs.
427
428**Atomic service API**: This API can be used in atomic services since API version 12.
429
430**System capability**: SystemCapability.Utils.Lang
431
432#### Attributes
433
434| Name   | Type   | Readable| Writable| Description                                                            |
435| ------- | ------- | ---- | ---- | ---------------------------------------------------------------- |
436| aborted | boolean | Yes  | Yes  | Whether to abort the operation. The value **true** means to abort the operation, and **false** means the opposite.                                          |
437| reason  | \<T>    | Yes  | Yes  | Reason for abort. This value will be used in the rejected Promise returned by [lockAsync](#lockasync).|
438
439## ArkTSUtils.ASON
440
441A utility class used to parse JSON strings into sendable data. ASON allows you to parse JSON strings and generate data that can be passed across concurrency domains. It also supports conversion from sendable data into JSON strings.
442
443### ISendable
444
445type ISendable = lang.ISendable
446
447**ISendable** is the parent type of all sendable types except null and undefined. It does not have any necessary methods or properties.
448
449**Atomic service API**: This API can be used in atomic services since API version 12.
450
451**System capability**: SystemCapability.Utils.Lang
452
453| Type| Description  |
454| ------ | ------ |
455| [lang.ISendable](js-apis-arkts-lang.md#langisendable)   | Parent type of all sendable types.|
456
457### Transformer
458
459type Transformer = (this: ISendable, key: string, value: ISendable | undefined | null) => ISendable | undefined | null
460
461Defines the type of the conversion result function.
462
463**Atomic service API**: This API can be used in atomic services since API version 12.
464
465**System capability**: SystemCapability.Utils.Lang
466
467**Parameters**
468
469| Name| Type  | Mandatory| Description           |
470| ------ | ------ | ---- | --------------- |
471| this   | [ISendable](#isendable) | Yes| Object to which the key-value pair to parse belongs.|
472| key  | string | Yes| Key to parse.|
473| value  | [ISendable](#isendable) | Yes| Value of the key.|
474
475**Return value**
476
477| Type| Description|
478| -------- | -------- |
479| [ISendable](#isendable) \| undefined \| null | **ISendable** object, undefined, or null.|
480
481### BigIntMode
482
483Enumerates the modes for processing BigInt.
484
485**Atomic service API**: This API can be used in atomic services since API version 12.
486
487**System capability**: SystemCapability.Utils.Lang
488
489| Name| Value| Description           |
490| ------ | ------ | --------------- |
491| DEFAULT   | 0 |BigInt is not supported.|
492| PARSE_AS_BIGINT   | 1 |Parses an integer that is less than -(2^53-1) or greater than (2^53-1) as BigInt.|
493| ALWAYS_PARSE_AS_BIGINT   | 2 |Parses all integers as BigInt.|
494
495### ParseReturnType
496
497Enumerates the return types of the parsing result.
498
499**System capability**: SystemCapability.Utils.Lang
500
501| Name| Value| Description           |
502| ------ | ------ | --------------- |
503| OBJECT   | 0 |Returns a **SendableObject** object.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
504| MAP<sup>13+</sup>   | 1 |Returns a **SendableMap** object.<br>**Atomic service API**: This API can be used in atomic services since API version 13.|
505
506### ParseOptions
507
508Describes the parsing options, which defines the BigInt processing mode and the return type of the parsing result.
509
510**Atomic service API**: This API can be used in atomic services since API version 12.
511
512**System capability**: SystemCapability.Utils.Lang
513
514| Name| Type| Mandatory| Description           |
515| ------ | ------ | ---- | --------------- |
516| bigIntMode   | [BigIntMode](#bigintmode) | Yes|Mode for processing BigInt.|
517| parseReturnType   | [ParseReturnType](#parsereturntype) | Yes|Return type of the parsing result.|
518
519### parse
520
521parse(text: string, reviver?: Transformer, options?: ParseOptions): ISendable | null
522
523Parses a JSON string to generate ISendable data or null.
524
525**Atomic service API**: This API can be used in atomic services since API version 12.
526
527**System capability**: SystemCapability.Utils.Lang
528
529**Parameters**
530
531| Name| Type  | Mandatory| Description           |
532| ------ | ------ | ---- | --------------- |
533| text   | string | Yes| Valid JSON string.|
534| reviver   | [Transformer](#transformer) | No| Conversion function. This parameter can be used to modify the value generated after parsing. The default value is undefined. Currently, only undefined can be passed in.|
535| options   | [ParseOptions](#parseoptions) | No| Parsing options. This parameter is used to control the type of the parsing result. The default value is undefined.|
536
537**Return value**
538
539| Type| Description|
540| -------- | -------- |
541| [ISendable](#isendable) \| null | ISendable data or **null** (if **null** is passed in).|
542
543**Example**
544
545```ts
546import { lang } from '@kit.ArkTS';
547
548type ISendable = lang.ISendable;
549let jsonText = '{"name": "John", "age": 30, "city": "ChongQing"}';
550let obj = ArkTSUtils.ASON.parse(jsonText) as ISendable;
551console.info((obj as object)?.["name"]);
552// Expected output: 'John'
553console.info((obj as object)?.["age"]);
554// Expected output: 30
555console.info((obj as object)?.["city"]);
556// Expected output: 'ChongQing'
557
558let options: ArkTSUtils.ASON.ParseOptions = {
559  bigIntMode: ArkTSUtils.ASON.BigIntMode.PARSE_AS_BIGINT,
560  parseReturnType: ArkTSUtils.ASON.ParseReturnType.OBJECT,
561}
562let numberText = '{"largeNumber":112233445566778899}';
563let numberObj = ArkTSUtils.ASON.parse(numberText,undefined,options) as ISendable;
564
565console.info((numberObj as object)?.["largeNumber"]);
566// Expected output: 112233445566778899
567
568let options2: ArkTSUtils.ASON.ParseOptions = {
569    bigIntMode: ArkTSUtils.ASON.BigIntMode.PARSE_AS_BIGINT,
570    parseReturnType: ArkTSUtils.ASON.ParseReturnType.MAP,
571  }
572let mapText = '{"largeNumber":112233445566778899}';
573let map  = ArkTSUtils.ASON.parse(mapText,undefined,options2);
574console.info("map is " + map);
575// Expected output: map is [object SendableMap]
576console.info("largeNumber is " + (map as collections.Map<string,bigint>).get("largeNumber"));
577// Expected output: largeNumber is 112233445566778899
578```
579
580### stringify
581
582stringify(value: ISendable | null | undefined): string
583
584Converts ISendable data into a JSON string.
585
586**Atomic service API**: This API can be used in atomic services since API version 12.
587
588**System capability**: SystemCapability.Utils.Lang
589
590**Parameters**
591
592| Name| Type| Mandatory| Description|
593| -------- | -------- | -------- | -------- |
594| value | [ISendable](#isendable) \| null \| undefined  | Yes| ISendable data.|
595
596**Return value**
597
598| Type| Description|
599| -------- | -------- |
600| string | JSON string.|
601
602**Example**
603
604```ts
605import { collections } from '@kit.ArkTS';
606
607let arr = new collections.Array(1, 2, 3);
608let str = ArkTSUtils.ASON.stringify(arr);
609console.info(str);
610// Expected output: '[1,2,3]'
611```
612
613### isSendable
614
615isSendable(value: Object | null | undefined): boolean
616
617Checks whether the passed-in value is of the sendable data type.
618
619**Atomic service API**: This API can be used in atomic services since API version 12.
620
621**System capability**: SystemCapability.Utils.Lang
622
623**Parameters**
624
625| Name| Type| Mandatory| Description|
626| -------- | -------- | -------- | -------- |
627| value | Object \| null \| undefined  | Yes| Object to check.|
628
629**Return value**
630
631| Type| Description|
632| -------- | -------- |
633| boolean | Check result. The value **true** means that the passed-in value is of the sendable data type, and **false** means the opposite.|
634
635**Example**
636
637```ts
638import { ArkTSUtils } from '@kit.ArkTS'
639
640@Sendable
641function sendableFunc()
642{
643  console.info("sendableFunc")
644}
645
646if (ArkTSUtils.isSendable(sendableFunc)) {
647  console.info("sendableFunc is Sendable");
648} else {
649  console.info("sendableFunc is not Sendable");
650}
651// Expected output: 'SendableFunc is Sendable'
652```
653