【HarmonyOS NEXT】异步编程的神器之Promise

1.背景

异步编程对 ArkTS 这门语言来说实在太重要。因为ArkTS是单线程模型【单线程模型指的是,JavaScript只在一个线程上运行。也就是说,JavaScript同时只能执行一个任务,其他任务都必须在后面排队等待。】

如果没有异步编程,很容易就写出回调地狱般的屎山代码。现在在ArkTS中要实现异步并发任务时,最合适的就是使用Promise和async/await【在此之前JS异步的发展历程是callback->promise/generator->async/await】

Promise和async/await提供异步并发能力,是标准的JS异步语法。异步代码会被挂起并在之后继续执行,同一时间只有一段代码执行,适用于单次I/O任务的场景开发,例如一次网络请求【底层是Native 线程】、一次文件读写【底层是Native 线程】等操作。

异步语法是一种编程语言的特性,允许程序在执行某些操作时不必等待其完成,而是可以继续执行其他操作。

2. Promise 是什么

用人话来讲:Promise是用来解决异步回调的一个语法糖【注意:这里的异步和线程是两回事注意:这里的异步和线程是两回事注意:这里的异步和线程是两回事,你在Promise里面写一个耗时操作也还是会阻塞主线程,想要解决只能使用线程,例如taskpool和workerTaskPool和Worker的对比】,这个语法糖还有一个业内通用的规范【Promises/A+规范】,利用这个规范你也可以自己手搓一个 Promise 【参考资料:https://www.ituring.com.cn/article/66566

用专业术语来讲:Promise 是 ECMAScript 2015 (ES6) 中引入的一个新的异步编程特性。【ES 是什么可以点这里查看:https://juejin.cn/post/7338783017123020812
在 ES6 之前,JavaScript 使用回调函数来处理异步操作,这种方式容易导致"回调地狱"的问题。Promise 的引入旨在解决这个问题,提供了一种更优雅和可读性更强的方式来处理异步操作。

官方文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

鸿蒙文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/async-concurrency-overview-V5

2.1 基本语法

2.1.1 创建Promise对象

const promise: Promise<void> = new Promise((resolve: Function, reject: Function) => {
   
   
    // 异步处理
    // 处理结束后、调用resolve(成功) 或 reject(失败)
})

2.1.2 使用Promise对象

2.1.2.1 promise.then

对通过new生成的promise对象为了设置其值在 resolve(成功) / reject(失败)时调用的回调函数 可以使用promise.then(onFulfilled, onRejected) 实例方法。

const promise: Promise<void> = new Promise((resolve: Function, reject: Function) => {
   
   
    // 异步处理
    // 处理结束后、调用resolve(成功) 或 reject(失败)
    setTimeout(() => {
   
   
      const randomNumber: number = Math.random();
      if (randomNumber > 0.5) {
   
   
        resolve(`${
     
     randomNumber}`);
      } else {
   
   
        reject(new Error('随机数太小'));
      }
    }, 1000);
})

promise.then((onFulfilled: string) => {
   
   
  console.info(`resolveResult ${
     
     resolveResult}`);//随机输出随机数
}, (onRejected: string) => {
   
   
  console.info(`rejectResult ${
     
     rejectResult}`);//随机抛出 随机数太小
})

resolve(成功)时
onFulfilled 会被调用
reject(失败)时
onRejected 会被调用
onFulfilled、onRejected 两个都为可选参数。
比如可以只实现onFulfilled

const promise: Promise<void> = new Promise((resolve: Function, reject: Function) => {
   
   
    // 异步处理
    // 处理结束后、调用resolve(成功) 
    setTimeout(() => {
   
   
      const randomNumber: number = Math.random();
      resolve(`${
     
     randomNumber}`);
    }, 1000);
})

promise.then((resolveResult: string) => {
   
   
  console.info(`resolveResult ${
     
     resolveResult}`);
})

2.1.2.2

另外一种语法是可使用promise.catch 拿到 onRejected 的结果,例如

const promise: Promise<string> = new Promise((resolve: Function, reject: Function) => {
   
   
      // 异步处理
    // 处理结束后、调用resolve(成功) 或 reject(失败)
    setTimeout(() => {
   
   
      const randomNumber: number = Math.random();
      if (randomNumber > 0.5) {
   
   
        resolve(`${
     
     randomNumber}`);
      } else {
   
   
        reject(new Error('随机数太小'));
      }
    }, 1000);
})
promise.then((resolveResult: string) => {
   
   
  console.info(`resolveResult ${
     
     resolveResult}`);
}).catch((catchRejectResult: string) => {
   
   
  console.error(`rejectResult ${
     
     catchRejectResult}`);
});
//会输出
//rejectResult >0.5 的数值
//或者输出
//rejectResult 随机数太小

如果同时实现了then.promise onRejected 和promise.catch。则promise.catch会不生效,例如:

const promise: Promise<string> = new Promise((resolve: Function, reject: Function) => {
   
   
  setTimeout(() => {
   
   
    try {
   
   
      throw new Error('随机数太小')
      resolve("成功了")
    } catch (e) {
   
   
      reject(e)
    }
  }, 1000);
})
promise.then((resolveResult: string) => {
   
   
  console.info(`resolveResult ${
     
     resolveResult}`);
},(catchRejectResult: Error)=>{
   
   
  console.error(`rejectResult ${
     
     catchRejectResult.message}`);
}).catch((catchRejectResult: Error) => {
   
   
  console.error(`catch rejectResult ${
     
     catchRejectResult.message}`);
})
//只会输出onRejected 中的回调,不会输出 catch中的
rejectResult 随机数太小

2.1.2.3 promise.finally

Promise 实例的 finally() 方法用于注册一个在 promise 敲定(兑现【reject】或拒绝【resolve】)时调用的函数。
例如我们可以在网络请求成功或者失败后关闭loading时使用这个方法

const promise: Promise<string> = new Promise((resolve: Function, reject: Function) => {
  //发起网络请求
})
promise.then((netResult: string) => {
  //网络请求成功
}).catch((netErrorResult: Error) => {
  //网络请求失败
}).finally(()=>{
  //网络请求结束
});

2.1.3 Promise的状态

用new Promise 实例化的promise对象有以下三个状态。

  • “has-resolution” - Fulfilled【已兑现状态】

resolve(成功)时。此时会调用 onFulfilled

  • “has-rejection” - Rejected【已拒绝】

reject(失败)时。此时会调用 onRejected

  • “unresolved” - Pending【待定】

既不是resolve也不是reject的状态。也就是promise对象刚被创建后的初始化状态等

为了保证程序的健壮性,Promise 里面的实现最好使用try catch 保证安全,因为在Arkts中,如果出现异常,则会导致App闪退【在Web端中不会】

2.1.3.1 错误的写法【模拟】

//这个写法会导致APP闪退
const promise: Promise<string> = new Promise((resolve: Function, reject: Function) => {
   
   
  setTimeout(() => {
   
   
    throw new Error('随机数太小')
  }, 1000);
})

2.1.3.2 正确的写法【模拟】

const promise: Promise<string> = new Promise((resolve: Function, reject: Function) => {
  setTimeout(() => {
    try {
      throw new Error('随机数太小')
      resolve("成功了")
    } catch (e) {
      reject(e)
    }
  }, 1000);
})
promise.then((resolveResult: string) => {
  console.info(`resolveResult ${resolveResult}`);
}).catch((catchRejectResult: string) => {
  console.error(`rejectResult ${catchRejectResult}`);
});

//会输出
rejectResult Error: 随机数太小

2.1.4 链式调用

promise.then 之后会返回一个 Promise 对象,可以进行下一个promise任务。在一些复杂业务上我们可以拆分多个子任务,依次向下执行

链式调用的几种写法:

2.1.4.1 Promise原始链式调用-写法1

new Promise<number>((resolve, reject) => {
   
   
  resolve(1)
}).then(data => {
   
   
  console.log("第一次对结果处理");
  return new Promise<number>((resolve, reject) => {
   
   
    resolve(data * 2<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冉冉同学_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值