【HarmonyOS Next】Promise你可能理解错了
记录一个很常见的认知误区,一段很简单的代码,在鸿蒙群里竟然都答错了。
用ArkTs开发鸿蒙产品,从前端转过来可能会更容易理解Promise、async、await。
1. 代码示例
下面是两段普通的ArkTs代码,如果你能很容易得出输出顺序,那么就可以跳过本篇文章了;
实际找了鸿蒙和前端群来说,答错的概率相当高。当然把ArkTs代码换成JS代码运行结果也是一样。
第一段代码,用setTimeout模拟延时,也是大部分博客模拟延时的方法。没理解为什么要用setTimeout模拟延时操作。
async myFunction() {
const result: string = await new Promise((resolve, reject) => {
setTimeout(() => {
console.info("C");
resolve('Hello, world!');
}, 1000);
});
return result;
}
// 入口
async aboutToAppear() {
console.info("A");
this.myFunction();
console.info("B");
}
第一段代码输出ABC,相信很多人都没疑问。
第二段代码,用for循环代替setTimeout模拟延时。
async myFunction() {
const result: string = await new Promise((resolve, reject) => {
for (let index = 0; index < 10000; index++) {
}
console.info("C");
resolve('Hello, world!');
});
return result;
}
// 入口
async aboutToAppear() {
console.info("A");
this.myFunction();
console.info("B");
}
结果输出ACB,无论this.myFunction()
方法前是否加上await
,结果都是ACB,有点懵了。
2. 解析
上诉两段代码,仅用for替代了setTimeout,为什么造成了结果不一致?
误区1:for与setTimeout都是模拟阻塞操作
误区2:Promise搭配async可以实现异步操作
(1) for循环是同步代码,setTimeout不是。
for循环在按顺序同步执行,没有什么好讲的;setTimeout是异步的宏任务。
JS中分为宏任务、微任务,宏任务包含setTimeout/setInterval等,微任务包含Promise.then。
执行顺序优先级是: 同步 > 微任务 > 宏任务
所以即使setTimeout的参数为0,它也不是立即执行,而是异步的宏任务。
(2) Promise只是解决异步回调的语法糖,方法体中不能异步,then是异步。
在Promise中写耗时操作会阻塞线程,如果想执行耗时操作,Promise解决不了问题,仍旧需要用线程(TaskPool和Worker)来实现异步操作。
所以Promise的诞生是为了更好的处理异步,让代码看起来简洁,在{}实现体中并不是真正可以异步,Promise.then是异步的微任务。
有一段前段代码证明Promise.then是异步的。
const main =async () => {
return new Promise ((resolve, reject)=>{
console.log('d');
if(true){
resolve('1')
}else{
reject('1')
}
console.log('a');
})
}
const init = async () =>{
let res= await main()
if(res == '1'){
console.log('c');
}
console.log('b');
}
输出dacb
3. 总结
Promise方法体中并不能带来异步能力,then方法体中是异步的微任务,且不能处理耗时任务。
总的来说Promise作用是能解决异步回调,使异步代码以同步的方式执行,不用太多callback。
鸿蒙文档描述:
Promise和async/await提供异步并发能力,是标准的JS异步语法。异步代码会被挂起并在之后继续执行,同一时间只有一段代码执行,适用于单次I/O任务的场景开发,例如一次网络请求、一次文件读写等操作。无需另外启动线程执行。
JS文档描述:
一个 Promise 是一个代理,它代表一个在创建 promise 时不一定已知的值。它允许你将处理程序与异步操作的最终成功值或失败原因关联起来。这使得异步方法可以像同步方法一样返回值:异步方法不会立即返回最终值,而是返回一个 promise,以便在将来的某个时间点提供该值。
这么看来JS文档中的描述更准确且更容易理解;并不是鸿蒙文档中的提供异步并发能力
。
对鸿蒙文档中的Promise和async/await提供异步并发能力
表示质疑,欢迎留言讨论。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。