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的结合

JS里的异步实例化的更多相关文章

  1. 理解 Node.js 里的 process.nextTick()

    有很多人对Node.js里process.nextTick()的用法感到不理解,下面我们就来看一下process.nextTick()到底是什么,该如何使用. Node.js是单线程的,除了系统IO之 ...

  2. js里的setTimeout和setInterval之后的页面是空白,阻塞浏览器的document对象,但是不阻塞script方法

    js里的setTimeout和setInterval是否进程阻塞? 阻塞浏览器的document对象,但是不阻塞script方法 当你在setTimeout中使用document.write时是不行的 ...

  3. Log4.Net 在Winfrom、MVC、ashx程序里的使用,ashx程序里使用异步

    最近做一个双11活动的,是一套相关的H5页面.本来以为难度不大,但是做下来几天还是遇到些问题.就总结一下吧,还是有收获的. 1.在H5页面中,有一个遮罩层,还是挺有意思的.直接用div+css控制遮罩 ...

  4. Log4.Net 在Winform、MVC、ashx程序里的使用,ashx程序里使用异步

    最近做一个双11活动的,是一套相关的H5页面.本来以为难度不大,但是做下来几天还是遇到些问题.就总结一下吧,还是有收获的. 1.在H5页面中,有一个遮罩层,还是挺有意思的.直接用div+css控制遮罩 ...

  5. 【本周面试题】第2周 - js单线程和异步相关问题

    硬性知识点考察: 为什么js是单线程的? 因为js设计最初是为了操作dom而生,如果是多线程的,当多个线程同时修改一个dom时就会产生冲突,所以设计成单线程,一次只能做一件事. 既然是单线程为什么要有 ...

  6. js多个异步请求

    一,两个(或多个)js异步并发执行,怎么在两个AJax异步操作之后执行一个新的操作 原题来自 ES6 方法 1.Promise 包装异步ajax操作,2.定义async 函数,3.用await等待pr ...

  7. 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?

    https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...

  8. uni-app如何解决在for循环里调用异步请求获取数据顺序混乱问题?

    总结/朱季谦 先前有一次做uni-app的js接口对接时,遇到过这样的情况,在for循环里,调用一个异步请求时,返回来的值顺序是乱的,因此,在以下的代码里,push到数组里的值,每次的顺序可能都是不一 ...

  9. PHP中的__toString方法(实现JS里的链式操作)

    _toString方法是在打印对象时自动调用的魔术方法,如果不声明会报以下错 Catchable fatal error: Object of class String could not be co ...

随机推荐

  1. Gin框架介绍与使用

    Gin // 初识 Gin框架 //下载(可能会下载不全.缺什么get什么即可) //go get -u -v github.com/gin-gonic/gin package main import ...

  2. Spring Cloud Alibaba Nacos Discovery 实战

    Nacos 作为服务注册中心,可以快速简单的将服务自动注册到 Nacos 服务端,并且能够动态无感知的刷新某个服务实例的服务列表,为分布式系统提供服务注册与发现功能 一.创建服务 1.创建项目 pom ...

  3. keepalived绑定单播地址、非抢占模式及LVS的TCP模式的高可用

    背景:keepalived默认是组播地址进行播放,且默认地址是224.0.0.18,如果配置多个keepalived主机,会导致虚拟IP地址存在冲突问题,这种问题怎么解决呢? 解决办法:就是将keep ...

  4. Docker Swarm(二)常用命令

    # 管理配置文件 docker config     # 查看已创建配置文件     - docker config ls     # 将已有配置文件添加到docker配置文件中     - dock ...

  5. Linux上使用iSCSI概述

    iSCSI简介 1. scsi和iscsi SCSI技术是存储设备最基本的标准协议,通常需要设备互相靠近并用SCSI总线连接,因此受到物理环境的限制 iSCSI(Internet Small Comp ...

  6. 进入除错模式!进入此模式后,将会出现更多的选项,分别是: · 以基本图形介面安装 CentOS 7 (使用标准显卡来设定安装流程图示); · 救援Centos系统; · 执行内存测试(Run a memory test);

    Centos 7.3 安装 0.0392017.07.14 20:12:09字数 1550阅读 985 Centos 7.3 基于 Red Hat 企业版的源代码的最新版本的 CentOS 7 在今年 ...

  7. Android屏幕适配全攻略(最权威的官方适配指导)屏幕尺寸 屏幕分辨率 屏幕像素密度 dpdipdpisppx mdpihdpixdpixxdpi

    Android屏幕适配全攻略(最权威的官方适配指导)原创赵凯强 发布于2015-05-19 11:34:17 阅读数 153734 收藏展开 转载请注明出处:http://blog.csdn.net/ ...

  8. Ubuntu 获取升级信息失败。可能网络有问题

    升级Ubuntu系统时遇到的这个问题, 原因是默认的源不是国内的,而且还可能导致下载慢等问题. 1.备份源 cd /etc/apt/ sudo cp sources.list sources.list ...

  9. 高可用 | Xenon:后 MHA 时代的选择

    原创:知数堂 | MySQL 高可用的选择 在 MySQL(5.5 及以下)传统复制的时代,MHA(Master High Availability)在 MySQL 高可用应用中非常成熟.在 MySQ ...

  10. Python3 url解码与参数解析

    Python3 url解码与参数解析 有些子节点名字直接就是编码后的url,就像下面这行一样: url='dubbo%3A%2F%2F10.4.5.3%3A20880%2Fcom.welab.auth ...