JS里的异步构造函数

众所周知,Js的构造函数是不能加上async/await来实现异步实例化的,一般当需要一个对象的属性是异步的结果时可以这样写:

//! 一个需要指定时间后返回的异步函数
function delay(timeout) {
return new Promise((resolve) => setTimeout(() => resolve("end"), timeout));
} class Test {
async init() {
this.end = await delay(1000);
}
}
(async function () {
const test = new Test(); //? 实例化
await test.init(); //? 初始化end属性
console.log(test.end);
})();

但是当我想要在实例化时就调用该属性时就还要调用一次init(),这未免太麻烦了,所以想要在实例化时就把该属性赋值,就像这样const test = await new Test()

这时找到了这篇文章,该作者提供了这样一段代码来实现了异步构造函数:

class MyClass {
constructor(timeout) {
this.completed = false const init = (async () => {
await delay(timeout)
this.completed = true delete this.then
return this
})() this.then = init.then.bind(init)
}
}
(async function(){
const myclass = await new MyClass(1000);
})()

在解释这段代码前就得说说PromiseLike了:一个有then方法,且该方法接收resolve,reject两个参数的对象,就像这样:

const PromiseLike = {
then(resolve) {
resolve("i am PromiseLike");
},
};
(async function () {
const something = await PromiseLike;
console.log(something); // i am PromiseLike
})();

即使PromiseLike不是一个函数,它也会被await调用对象里的then方法并resolve出结果

现在回到刚才那段代码,注意到它最后的一段了吗

this.then = init.then.bind(init)

这句话把一个异步函数initthen给了实例,所以在调用new Myclass 后得到的实例上有着一个then方法,这个then方法又会被前面的await解析,这时实质上解析的就是init这个异步函数的then而这个then返回的是该类的实例化删除then后的this

这样await new MyClass()会等到init的异步执行完毕才会返回值,这个返回值是init的resolve。

总结一下:该方法其实仍然是同步实例化出了对象,但是await会马上异步执行实例化里then,然后返回出then里删除了then方法的this,这样就做到了一句话进行实例化并初始化异步属性。

知道了这个原理后,最初的问题就解决了:

class Test {
constructor() {
const init = (async () => {
this.end = await delay(1000);
delete this.then;
return this;
})();
this.then = init.then.bind(init);
}
}
(async function () {
const test = await new Test();
console.log(test.end); // end
})();

该作者也提供了一个基类用来继承出异步构造函数,可以到原文去看看。

参考:异步构造函数 - 构造函数与Promise的结合

最新文章

  1. Java开发环境配置
  2. Change Eclipse Tooltip's Color in Ubuntu
  3. Sprint第三个冲刺(第六天)
  4. memcached 介绍
  5. win32 listbox
  6. C#网络编程简单实现通信小例子-2
  7. Duanxx的技术问题:word界面显示模糊
  8. DKNY_百度百科
  9. Java8 Lamdba表达式 001
  10. 444A/CF
  11. 在 Mac OS 上编译 FFmpeg
  12. Newtonsoft.Json输出Json时动态忽略属性
  13. zabbix-3.4.14源码安装
  14. DL_1_week1_概论
  15. ZOJ - 2853 Evolution 线性变换变成矩阵快速幂
  16. Windows栈溢出原理
  17. Spring实战 MethodInvokingJobDetailFactoryBean使用与分析
  18. 选择排序之C++实现
  19. HDU 1535
  20. PyQt5 中调用MySql接口失败 ( QSqlDatabase 组件) 在Linux环境下如何修改

热门文章

  1. Django(34)Django操作session(超详细)
  2. openshift 3.11 安装部署
  3. iozone测试方法-20191008
  4. Mycat调优启用useOffHeapForMerge报java.lang.NumberFormatException异常解决(附源码)
  5. :整数 跳转到该行 Vim中常用的命令
  6. nginx的四层转发功能
  7. CentOS7安装vncserver(启动失败及连接黑屏解决办法)
  8. nosql数据库之Redis持久化、备份和主从配置
  9. fdisk 磁盘分区命令
  10. system verilog内建数据类型