如何在类的新对象内部调用构造函数?以及如何在Promise中正确调用类的logger成员?
咱们一个个来解决你的问题~
在类的实例内部调用当前类的构造函数,有几种灵活的方式,不用硬编码类名,还能适配继承场景:
使用
new this.constructor(...):this.constructor会指向当前实例所属的类,不管是父类还是子类,都能正确调用对应类的构造函数。举个例子:class MyClass { constructor(name) { this.name = name; } createNewInstance(newName) { // 调用当前类的构造函数生成新实例 return new this.constructor(newName); } } const instance1 = new MyClass('Alice'); const instance2 = instance1.createNewInstance('Bob'); console.log(instance2.name); // 输出 'Bob'如果是在构造函数内部想复用构造逻辑,可以用
new.target(...)(ES6+支持):new.target指向被new调用的构造函数,同样能适配继承,比如处理参数默认值的场景:class MyClass { constructor(name) { if (typeof name !== 'string') { // 重新调用构造函数传入默认值 return new.target('Default Name'); } this.name = name; } } const instance = new MyClass(123); console.log(instance.name); // 输出 'Default Name'
要是在静态方法里调用构造函数,直接用new this(...)就行,因为静态方法里的this指向类本身。
this.logger.error()的解决方案 看了你的代码,问题核心是回调函数的this指向不对!你用了普通函数作为s3.upload的回调,这个普通函数的this不指向MyClass的实例,而是指向s3.upload的内部上下文,所以找不到this.logger。给你几个靠谱的解决方法:
方法1:箭头函数(最推荐,代码最简洁)
箭头函数不会绑定自己的this,它会继承外层作用域的this(也就是uploadfile方法里的MyClass实例)。修改后代码如下:
async uploadfile(buffer, key: string): Promise<string> { const params = { "Body": buffer, "Bucket": 's3Bucket', "Key": key, "ContentType": 'application/pdf', "ACL": 'public-read', }; const path: string = await new Promise((resolve, reject) => { // 把普通回调改成箭头函数 s3.upload(params, (err, data) => { if (err) { this.logger.error('Error', err); // 现在this正确指向MyClass实例了 reject('Error occurred'); } resolve(data.Location); }); }); return path; }
方法2:提前保存this到变量
在new Promise之前,把当前实例的this存到一个变量(比如that),然后在回调里用这个变量访问logger:
async uploadfile(buffer, key: string): Promise<string> { const params = { "Body": buffer, "Bucket": 's3Bucket', "Key": key, "ContentType": 'application/pdf', "ACL": 'public-read', }; const that = this; // 保存当前实例的this const path: string = await new Promise((resolve, reject) => { s3.upload(params, function(err, data) { if (err) { that.logger.error('Error', err); // 使用that访问logger reject('Error occurred'); } resolve(data.Location); }); }); return path; }
方法3:用bind()绑定this
给回调函数绑定当前实例的this,强制让回调里的this指向MyClass实例:
async uploadfile(buffer, key: string): Promise<string> { const params = { "Body": buffer, "Bucket": 's3Bucket', "Key": key, "ContentType": 'application/pdf', "ACL": 'public-read', }; const path: string = await new Promise((resolve, reject) => { // 用bind把当前实例的this绑定到回调函数 s3.upload(params, function(err, data) { if (err) { this.logger.error('Error', err); reject('Error occurred'); } resolve(data.Location); }.bind(this)); }); return path; }
额外小建议
如果你的AWS SDK版本支持Promise化调用,其实可以不用手动封装new Promise,直接用s3.upload(params).promise(),这样代码更简洁,还能彻底避开this的问题:
async uploadfile(buffer, key: string): Promise<string> { const params = { "Body": buffer, "Bucket": 's3Bucket', "Key": key, "ContentType": 'application/pdf', "ACL": 'public-read', }; try { const data = await s3.upload(params).promise(); return data.Location; } catch (err) { this.logger.error('Error', err); throw new Error('Error occurred'); } }
内容的提问来源于stack exchange,提问作者pasindu229

