嘿,我对函数的原型和固有性有疑问。您能否解释一下如何从构造函数返回arr并将此arr添加到原型中?
var example = new Constructor() function Constructor(){ Service.getService().then(function(data){ this.arr = data.data.array; return this.arr }) } Constructor.prototype.getArray = function(){ console.log(this.arr) }) example.getArray();
并且在getArraythis.arr中是未定义的。Service and getService()有角度的工厂以及前端和后端之间的连接
getArray
Service and getService()
将异步操作放入构造函数中特别困难。这有几个原因:
由于这些原因,您通常不希望在构造函数中执行异步操作。IMO,下面最干净的体系结构是工厂函数,它返回一个可解析为最终对象的承诺。您可以在工厂函数中执行任意数量的异步工作(调用对象上的任何方法),并且直到对象完全形成后,才将其公开给调用方。
这些是处理该问题的各种选项中的一些:
使用返回承诺的工厂函数
这使用了工厂功能,可以为您完成一些更常见的工作。在完全初始化之前,它也不会显示新对象,这是一个很好的编程习惯,因为调用者不会偶然尝试使用尚未完成异步处理的部分形成的对象。factory函数选项还通过拒绝返回的promise干净地传播错误(同步或异步):
// don't make this class definition public so the constructor is not public class MyObj() { constructor(someValue) { this.someProp = someValue; } init() { return Service.getService().then(val => { this.asyncProp = val; return this; }); } } function createMyObj(someValue) { let x = new MyObj(someVal); return x.init(); } createMyObj(someVal).then(obj => { // obj ready to use and fully initialized here }).catch(err => { // handle error here });
如果使用模块,则只能导出工厂函数(无需导出类本身),从而强制执行对象正确初始化,并且在完成初始化之前不使用该对象。
将异步对象初始化分为可以返回承诺的单独方法
class MyObj() { constructor(someValue) { this.someProp = someValue; } init() { return Service.getService().then(val => { this.asyncProp = val; }); } } let x = new MyObj(someVal); x.init().then(() => { // ready to use x here }).catch(err => { // handle error });
使用事件表示完成
许多与I / O相关的API中都使用了该方案。通常的想法是,您从构造函数中返回一个对象,但是调用者知道该对象直到发生特定事件才真正完成其初始化。
// object inherits from EventEmitter class MyObj extends EventEmitter () { constructor(someValue) { this.someProp = someValue; Service.getService().then(val => { this.asyncProp = val; // signal to caller that object has finished initializing this.emit('init', val); }); } } let x = new MyObj(someVal); x.on('init', () => { // object is fully initialized now }).on('error', () => { // some error occurred });
将异步操作放入构造函数的骇人方式
尽管我不建议您使用此技术,但这是将异步操作放入实际构造函数本身的过程:
class MyObj() { constructor(someValue) { this.someProp = someValue; this.initPromise = Service.getService().then(val => { this.asyncProp = val; }); } } let x = new MyObj(someVal); x.initPromise.then(() => { // object ready to use now }).catch(err => { // error here });
注意,您会在各种API的许多地方看到第一个设计模式。例如,对于node.js中的套接字连接,您将看到以下内容:
let socket = new net.Socket(...); socket.connect(port, host, listenerCallback);
套接字是在第一步中创建的,但随后在第二步中已连接到某些对象。而且,同一个库具有工厂功能net.createConnection(),该功能将这两个步骤组合为一个功能(上述第二个设计模式的说明)。该net模块实例并不碰巧使用诺言(很少有原创的NodeJS的API做),但它们完成使用回调和事件相同的逻辑。
net.createConnection()
net
有关代码的其他说明
您this的代码中的值可能也有问题。一个.then()处理程序不自然保护的价值this从周围环境中如果你传递一个普通function() {}的参考。因此,在此:
this
.then()
function() {}
function Constructor(){ Service.getService().then(function(data){ this.arr = data.data.array; return this.arr }) }
this当您尝试做时的值将this.arr = data.data.array;是不正确的。解决ES6中该问题的最简单方法是改为使用粗箭头功能:
this.arr = data.data.array;
function Constructor(){ Service.getService().then(data => { this.arr = data.data.array; return this.arr }); }