1# ArkTS运行时常见问题 2<!--Kit: ArkTS--> 3<!--Subsystem: ArkCompiler--> 4<!--Owner: @DaiHuina1997--> 5<!--Designer: @yao_dashuai--> 6<!--Tester: @kirl75; @zsw_zhushiwei--> 7<!--Adviser: @foryourself--> 8 9## 方舟正则运算与预期输出结果不一致场景 10 11如果使用方舟正则运算时结果与期望不符,请检查以下场景。 12 13### 方舟正则运算对于\b处理与预期不一致 14 15 ```ts 16 let str = "\u2642"; 17 let res = str.replace(/\b/g, "/"); 18 console.info("res = " + res); 19 // 期望输出: res = ♂ 20 // 实际输出: res = /♂/ 21 ``` 22 23 规避方案:暂无。 24 > **说明:** 25 > 26 > 正则匹配\b(单词边界)遇到某些ASCII编码之外的字符时,会将其当成ASCII字符来处理,从而将不是单词边界匹配识别成单词边界。 27 28### 方舟正则运算对于先行断言((?=pattern)或(?!pattern)) 嵌套在后行断言((?<=pattern)或(?<!pattern))内部的场景与预期不一致 29 30 ```ts 31 console.info(`res:${"abcdef".match(/(?<=ab(?=c)cd)ef/)}`); 32 // 期望输出: res:ef 33 // 实际输出: res:null 34 ``` 35 36 规避方案:使用/(?<=abcd)ef/代替/(?<=ab(?=c)cd)ef/。 37 38### 方舟正则运算对于大小写的处理与预期不一致 39 40 ```ts 41 let res = /\u{10400}/ui.test("\u{10428}"); 42 console.info("res = " + res); 43 // 期望输出: res = true 44 // 实际输出: res = false 45 ``` 46 47 规避方案:暂无。 48 49### 方舟正则运算/()/ug匹配时lastIndex与预期不一致 50 51 ```ts 52 let L = "\ud800"; 53 let T = "\udc00"; 54 let u = /()/ug; 55 u.lastIndex = 1; 56 u.exec(L + T + L + T); 57 console.info("u.lastIndex = " + u.lastIndex); 58 // 期望输出: u.lastIndex = 0 59 // 实际输出: u.lastIndex = 1 60 ``` 61 62 规避方案:暂无。 63 64### 方舟正则运算[]内部使用'-'与预期不一致 65 66 ```ts 67 let str = "a-b"; 68 let reg = /[+-\s]/; 69 console.info("reg.exec(str) = " + reg.exec(str)); 70 // 期望输出: reg.exec(str) = - 71 // 实际输出: reg.exec(str) = null 72 ``` 73 74 规避方案:使用转义后的"-"。 75 ```ts 76 let str = "a-b"; 77 let reg = /[+\-\s]/; 78 console.info("reg.exec(str) = " + reg.exec(str)); 79 ``` 80 81### 方舟正则运算具名捕获组获取与预期不一致 82 83 ```ts 84 let reg = new RegExp("(a)(?<b>b)"); 85 let res = reg.exec("ab"); 86 console.info("JSON.stringify(res?.groups) = " + JSON.stringify(res?.groups)); 87 // 期望输出: JSON.stringify(res?.groups) = {"b":"b"} 88 // 实际输出: JSON.stringify(res?.groups) = {"b":"a"} 89 ``` 90 91 规避方案:计算具名捕获组位置获取具名捕获组匹配的内容。 92 93 ```ts 94 let reg = new RegExp("(a)(?<b>b)"); 95 let res = reg.exec("ab") as Array<string>; 96 console.info(JSON.stringify(res[2])); 97 ``` 98 99### 方舟正则匹配使用'|'与预期不一致 100 101 在使用正则匹配时,如果'|'前是一个空匹配,会导致'|'后的匹配不成功。 102 103 ```ts 104 let reg = /a(?:|x)$/; 105 let res = reg.exec("ax"); 106 console.info("JSON.stringify(res) = " + JSON.stringify(res)); 107 // 期望输出: JSON.stringify(res) = ["ax"] 108 // 实际输出: JSON.stringify(res) = null 109 ``` 110 111 规避方案:使用reg2或reg3替换reg1。 112 113 ```ts 114 let reg1 = /a(?:|x)$/; 115 let reg2 = /a(?:x)?$/; 116 let reg3 = /a(?:x){0,1}$/; 117 ``` 118 119### 方舟字符串 `replace` 接口对于第一个参数为空字符串的场景与预期不一致 120 121 在使用字符串replace接口时,如果第一个参数是空字符串,则直接返回原始字符串。 122 123 ```ts 124 let str = "dddd" 125 let res = str.replace("", "abc"); 126 console.info("res = " + res); 127 // 期望输出: res = abcdddd 128 // 实际输出: res = dddd 129 ``` 130 131 规避方案:使用正则表达式 `/^/` 表示字符串起始符,作为第一个参数。 132 133 ```ts 134 let str = "dddd" 135 let res = str.replace(/^/, "abc"); 136 ``` 137 138## Async函数内部异常的处理机制 139 140**场景** 141 142如果在Async函数内部产生了异常,且没有使用catch捕获该异常,在ArkTS中不会导致进程退出。其本质是Async函数返回了一个rejected状态的Promise对象,没有被处理,使得Promise的rejected状态没有被捕获。Async函数内部的异常会变成 unhandledRejection,表现为异常未抛出。 143 144**Async函数内部异常的捕获方式** 145 1461. 使用[errorManager.on()](../reference/apis-ability-kit/js-apis-app-ability-errorManager.md#errormanageronerror)捕获到Async函数产生的unhandledrejection事件,再通过编写errorManager.on()注册的回调函数,来进行异常处理操作。 147 148 ```ts 149 errorManager.on("unhandledRejection", (a:ESObject, b:Promise<ESObject>) => { 150 console.info("Async test", a); 151 }) 152 ``` 153 1542. 在Async函数内部,针对可能发生异常的代码块添加try-catch逻辑,直接捕获可能出现的异常。 155 156> **注意:** 157> 158> 注意必须在Async函数内部,外部无法捕获Async函数内部的异常,外部只能通过errorManager.on()监听。 159 160 161**查看Async函数内部是否有异常的方式** 162 163若开发者仅需要查看Async函数内部是否产生异常,首先需要在DevEco Studio终端执行以下hilog命令开启debug级别日志打印: 164 165```shell 166 hilog -b D 167``` 168 169然后点击DevEco Studio下方HiLog选项卡,输入过滤条件“Throw error:”,即可查看到Async函数内产生的异常信息。 170 171 172## 方舟Array.flatMap()接口常见问题 173 174Array.flatMap()接口在处理包含Proxy的Array时,未正确展平嵌套的Proxy Array,导致返回结果与预期不一致。 175 176### ArkTS使用场景 177 178```ts 179let arr1 = [0, 1]; 180let arr2 = [2, 3]; 181const emptyHandler = new Object() as ProxyHandler<number[]>; 182let proxy1 = new Proxy(arr1, emptyHandler); 183let proxy2 = new Proxy(arr2, emptyHandler); 184let arr3 = [proxy1, proxy2]; 185let res = arr3.flatMap(x => x); 186 187console.log("res length:", res.length.toString()); 188// 期望输出: res length: 4 189// 实际输出: res length: 2 190console.log("res[0] is: ", res[0].toString()); 191// 期望输出: res[0] is: 0 192// 实际输出: res[0] is: 0,1 193``` 194 195### ArkUI使用场景 196 197ArkUI状态管理框架会为使用状态变量装饰器(如@State、@Trace、@Local)装饰的Array添加一层代理,用于观测API调用产生的变化。如果状态修饰器与Array组合,并且调用Array.flatMap,会出现如下问题。 198 199以状态管理V2为例: 200 201```ts 202@Entry 203@ComponentV2 204struct Index { 205 @Local p: number[] = [0, 1]; 206 @Local q: number[] = [2, 3]; 207 c: number[][] = [this.p, this.q]; 208 d: number[] = []; 209 210 aboutToAppear(): void { 211 this.d = this.c.flatMap(it => it); 212 } 213 214 build() { 215 Column() { 216 Text(`${this.d[0]}`); // 预期显示:0; 实际显示:0,1 217 } 218 } 219} 220``` 221 222### Array.flatMap规避方案 223 224避免使用Array.flatMap()接口,改为调用Array.map()接口后再调用深度为1的Array.flat()接口。以上文ArkTS使用场景为例: 225 226```ts 227// 使用规避方案前 228let res = arr3.flatMap(x => x); 229// 使用规避方案后 230let res = arr3.map(x => x).flat(); 231```