JavaScript之异步构造方法总结【异步构造函数 - 构造函数与Promise的结合】

import {AsyncConstructor} from "async-constructor";
import UtilType from "../utils/UtilType.js";


export default class OwnAsyncConstructor extends AsyncConstructor {
    constructor(contact_class, mnemonic = null, asyncFunc = null) {
        /**
         * 功能:实现异步构造函数【同时兼容同步和异步的场景】
         * 特殊说明:
         *      1、既然为异步构造函数,那么继承子类给this对象添加属性必须全部在asyncFunc方法实现!
         *      2、在继承子类的构造函数中,this对象为一个promise对象,为此asyncFunc方法内部才是this原始对象!
         *      3、【注】使用异步构造函数实现【异步实例】JavaScript的语法提示不是很管用!
         * 参数:
         *      asyncFunc:需异步初始化的其他功能【继承子类为this添加属性,必须在此方法实现】
         */
        super(async () => {
            UtilType.isFunction(asyncFunc) ? await asyncFunc() : null;
        });
    }

    static async createAsyncInstance(async_class) {
        /**
         * 功能:封装一个通用创建异步类实例的方法!
         */
        return await new async_class()
    }
};

JavaScript默认的构造函数只能执行同步代码, 无法执行异步代码,

构造函数异步的实现原理参考:

异步构造函数 - 构造函数与Promise的结合参考:BlackGlory and his digital garden

参考2:https://github.com/BlackGlory/async-constructor

使用别人封装号的即可

npm i async-constructor

异步构造基类: 更好的使用方式

对于第二种异步构造函数, 我们可以把它编写成基类, 这种方式相比直接编写第二种异步构造函数要安全得多, 同时也比第一种异步构造方式看起来更接近其他编程语言的习惯(毕竟当初加入class关键字就是为了这个目的), 不需要手动编写return this. 除了自己编写基类, 你也可以在async-constructor找到我已经做好的模块.

基类形式非常简单, 我们只需要在最小化形式上进行扩展即可:

class AsyncConstructor {
  constructor(asyncConstructor) {
    const init = (async () => {
      await asyncConstructor()
      delete this.then
      return this
    })()
    this.then = init.then.bind(init)
  }
}

在使用时, 继承AsyncConstructor类, 将异步箭头函数作为基类的参数传入super:

function delay(timeout) {
  return new Promise(resolve => setTimeout(() => resolve(), timeout))
}

class MyClass extends AsyncConstructor {
  constructor(timeout) {
    super(async () => {
      await delay(timeout)
      this.completed = true
    })

    this.completed = false
  }
}

;(async () => {
  const a = await new MyClass(5000)
  console.log(a.completed) // true
})()

之所以说这种方式让第二种异步构造函数更加安全, 是因为在这种使用方式里, 你的"init函数"内永远有await操作符, 即使你传入的是一个同步函数, 它也不会出现上面提到的问题. 此外, 在往super里传入参数时, 我们还能额外获得来自运行时的错误检查: 在大多数情况下我们需要在异步构造函数里修改this的成员, 若你传入的是一个同步函数, 而这个同步函数里又用到了this, 运行时将直接爆出错误ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor, 原因是我们的基类此时还没有构造完成. 相反, 在传入async函数的情况下, 基类已经构造完成了, 使用起来就没有任何问题, 通过这种方式, 可使开发人员避免在此编写同步代码.

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值