使用 async

使用async语法开发业务,代码以更整洁优雅的方式替代 Callback 与 Promise

通过本节,你将学会:

  • 如何配置async语法的 babel 编译支持
  • 使用async, await语法
  • 在 native 接口中使用async

如何配置 async 语法的 babel 编译支持

传统前端开发中,异步的处理方式有:Callback、Promise、Generator;这几种代码的书写方式,后者往往比前者可读性好很多;ECMA 规范中新的语法方式async以一种更优雅的方式来处理异步

当前应用平台本身仅支持ES5的语法,所以要支持它必须借助babel之类的语法分析转换工具,同时还要在代码中注入polyfill

那么开发者可以把@babel/runtime/regenerator注入到app.ux中,因为这个文件是所有页面脚本执行前都会执行的

示例如下:

  1. // 脚本:regenerator.js
  2. // 注意:仅用于注入类库函数,不允许存储页面组件等数据
  3. const injectRef = Object.getPrototypeOf(global) || global
  4. // 注入regeneratorRuntime
  5. injectRef.regeneratorRuntime = require('@babel/runtime/regenerator')
  6. // 如果使用的 hap-toolkit 版本低于0.0.38(babel 版本低于 7),则按下面的方式引入
  7. // injectRef.regeneratorRuntime = require('babel-runtime/regenerator')

app.ux中引入这个脚本文件,就可以注入对async的支持(在项目编译后的build/app.js中搜索regeneratorRuntime即可发现注入成功)

使用 async, await 语法

关于语法使用可以参考外部文档Exploring ES2016 and ES2017等,这里不做过多讲解

示例如下:

  1. <script>
  2. export default {
  3. private: {},
  4. onInit () {
  5. this.$page.setTitleBar({ text: '支持AsyncAwait' })
  6. },
  7. onReady () {
  8. this.testAsync()
  9. },
  10. /**
  11. * 测试Async
  12. */
  13. testAsync () {
  14. async function bar () {
  15. return 'bar'
  16. }
  17. async function foo() {
  18. const ret1 = await bar();
  19. console.info('PAGE: foo: ', ret1)
  20. }
  21. foo()
  22. }
  23. }
  24. </script>

在 native 接口中使用 async

Native 接口直接返回 Promise 1010+

该方法仅支持 platformVersion 1010+ 的异步接口。

关于异步接口的更多信息,详见文档 接口

示例如下:

  1. <script>
  2. import fetch from '@system.fetch'
  3. export default {
  4. async onReady () {
  5. // 成功示例
  6. try {
  7. const response = await fetch.fetch({
  8. url: 'https://statres.quickapp.cn/quickapp/quickapptool/release/platform/quickapp_platform.json',
  9. })
  10. console.info('fetch 成功 code: ', response.data.code)
  11. console.info('fetch 成功 data: ', response.data.data)
  12. console.info('fetch 成功 headers: ', JSON.stringify(response.data.headers))
  13. } catch(err) {
  14. console.info('fetch 失败 code: ', err.code)
  15. console.info('fetch 失败 data: ', err.data)
  16. }
  17. // 失败示例
  18. try {
  19. const response = await fetch.fetch({
  20. url: 'http://www.Its_A_Wrong_URL.com/',
  21. })
  22. console.info('fetch 成功 code: ', response.data.code)
  23. console.info('fetch 成功 data: ', response.data.data)
  24. console.info('fetch 成功 headers: ', JSON.stringify(response.data.headers))
  25. } catch(err) {
  26. console.info('fetch 失败 code: ', err.code)
  27. console.info('fetch 失败 data: ', err.data)
  28. }
  29. }
  30. }
  31. </script>

Native 接口返回 callback

对于 platformVersion 低于 1010 的设备,以及非异步回调的方法,要想以 async 的方式使用 native 接口,需要对 native 接口进行改造,从返回callback方式到返回Promise方式,同时定义async方法返回。

我们同样以 fetch 接口为例

示例如下:

  1. // asyncNatives.js
  2. import nativeFetch from '@system.fetch'
  3. const natives = {
  4. /**
  5. * 网络请求
  6. * @param options
  7. * @return {Promise}
  8. */
  9. async fetch(options) {
  10. const p1 = new Promise((resolve, reject) => {
  11. options.success = function(data, code) {
  12. resolve({ data, code })
  13. }
  14. options.fail = function(data, code) {
  15. reject({ data, code })
  16. }
  17. nativeFetch.fetch(options)
  18. })
  19. return p1
  20. }
  21. }
  22. export { natives }

改造 fetch 接口,暴露natives变量到app对象上;

调用async版本的 fetch 接口的示例代码如下:

  1. <script>
  2. export default {
  3. onReady () {
  4. this.testMockNatives()
  5. },
  6. /**
  7. * 测试async的native接口
  8. */
  9. async testMockNatives () {
  10. const { natives } = this.$app.$def
  11. // 成功示例
  12. const ret1 = await natives.fetch({
  13. url: 'https://statres.quickapp.cn/quickapp/quickapptool/release/platform/quickapp_platform.json',
  14. })
  15. console.info('fetch成功结果: ', JSON.stringify(ret1))
  16. // 失败示例
  17. const ret2 = await natives.fetch({
  18. url: 'http://www.Its_A_Wrong_URL.com/'
  19. })
  20. console.info('fetch失败结果: ', JSON.stringify(ret2))
  21. }
  22. }
  23. </script>

总结

本节不是开发的必须部分,只是为开发者提供一种更优雅的异步处理方式,推荐感兴趣的同学使用