[英]How to create a Javascript (es5) constructor function containing an asynchronous call
I'm trying to create a constructor function that includes a call to indexedDB or localStorage to retrieve some data if it exists and then populate it's values, either from the cache or the given (default) data.我正在尝试创建一个构造函数 function ,其中包括对 indexedDB 或 localStorage 的调用,以检索一些数据(如果存在),然后从缓存或给定(默认)数据中填充它的值。
I had it working, but somehow broke my code.我让它工作,但不知何故破坏了我的代码。 Given that my method of programming is "hit it with a stick until it works", the code is an absolute mess.
鉴于我的编程方法是“用棍子敲打直到它起作用”,代码绝对是一团糟。 So I have simplified the problem down to a contrived example, which fails in the same way.
所以我将问题简化为一个人为的例子,它以同样的方式失败。
Removing the async function (setTimeout) fixes the problem, but then my code won't work.删除异步 function (setTimeout) 可以解决问题,但是我的代码将无法正常工作。
var person = (function(){
function privateFn (value){
return value;
}
function private_asyncFn(value, callback){
setTimeout(function () {
return callback(value);
}, 10);
}
var DATA, NUM;
var personConstructor = function(name, age, gender, callback){
this.name = privateFn(name);
this.gender = privateFn(gender);
DATA = DATA || [];
NUM = NUM || 0;
this.num = NUM;
private_asyncFn(age, function(ret){
DATA[NUM++] = { name: this.name, age: ret };
if (callback instanceof Function) return callback(this.name);
}.bind(this));
};
personConstructor.prototype.getAge = function () {
if (this.gender === "male") return DATA[this.num].age;
else return DATA[this.num].age < 20 ? 18 : (Math.floor(DATA[this.num].age / 10) - 1) + "9 and holding";
};
return personConstructor;
})();
var name1;
var person1 = new person("jill", 32, "female", function(name){
name1 = name;
});
var age1 = person1.getAge(); //Uncaught TypeError: Cannot read property 'age' of undefined????
I see other code on SO using classes and promises and async/await, but I don't understand how that all works, so this code is a bit "old school", sorry about that.我在 SO 上看到了使用类和承诺以及异步/等待的其他代码,但我不明白这一切是如何工作的,所以这段代码有点“老派”,对此感到抱歉。
In this example, can you retrieve the age of the person, immediately following the initialization of a new person?在这个例子中,你能在新人初始化之后立即检索人的年龄吗?
There is no way to make an asynchronous constructor.没有办法制作异步构造函数。 What you want to do instead is probably create an asynchronous function that will yield your constructed object after the asynchronous operation is completed.
您想要做的可能是创建一个异步 function ,它将在异步操作完成后生成您构造的 object 。 I'd give you a more concrete example, but frankly, I don't understand what the async part of your code is attempting to do.
我会给你一个更具体的例子,但坦率地说,我不明白你的代码的异步部分试图做什么。 Here's an example of how you might accomplish this, though:
不过,这是一个如何完成此操作的示例:
function Person(name, age, gender) {
this.name = name
this.gender = gender
this.age = age
}
Person.prototype.getAge = function() {
return this.age
}
Person.create = function create(name, age, gender, done) {
var person = new Person(name, age, gender)
setTimeout(function () {
done(null, person)
}, 1000)
}
Person.create("jill", 32, "female", function (person) {
person.getAge()
})
I would recommend using Promises and ES6 classes if you don't need to support very old browsers.如果您不需要支持非常旧的浏览器,我建议您使用 Promises 和 ES6 类。
class Person {
static create(name, age, gender) {
return new Promise(resolve => {
const person = new Person(name, age, gender)
resolve(person)
})
}
constructor(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
getAge() {
return this.age
}
}
Person.create("jill", 32, "female")
.then((person) => {
person.getAge()
})
It would be helpful when you post your next SO question to give a real world example of what your code is trying to achieve - getAge
returning different results depending on gender doesn't make much sense:)当您发布下一个 SO 问题以给出您的代码试图实现的目标的真实示例时,这将很有帮助 -
getAge
根据性别返回不同的结果没有多大意义:)
By moving all of the async logic into an init
function that is called after creating a new person
keeps the constructor synchronous.通过将所有异步逻辑移动到在创建
new person
后调用的init
function 中,可以使构造函数保持同步。 Then getAge
can be called from inside the init
callback function using either this.getAge()
or person1.getAge()
(because person1 exists now)然后可以使用
getAge
this.getAge()
或person1.getAge()
从init
回调 function 内部调用 getAge(因为 person1 现在存在)
var person = (function(){
function privateFn (value){
return value;
}
function private_asyncFn(value, callback){
setTimeout(function () {
return callback(value);
}, 10);
}
var DATA, NUM;
//removed all data inputs and callback from constructor function
var personConstructor = function(){
//initialise publically accessible data
this.name = null;
this.gender = null;
//initialise blank data store
DATA = DATA || [];
NUM = NUM || 0;
this.num = NUM;
DATA[NUM++] = {
age: null
};
};
//created new init function
personConstructor.prototype.init = function (name, age, gender, callback){
this.name = privateFn(name);
this.gender = privateFn(gender);
private_asyncFn(age, function(ret){
DATA[this.num].age = ret;
//note: .call(this,...) on the callback to use "this" in the callback
if (callback instanceof Function) return callback.call(this, this.name);
}.bind(this));
};
personConstructor.prototype.getAge = function () {
if (this.gender === "male") return DATA[this.num].age;
else return DATA[this.num].age < 20 ? 18 : (Math.floor(DATA[this.num].age / 10) - 1) + "9 and holding";
};
return personConstructor;
})();
var name1, age1;
var person1 = new person();
person1.init("jill", 32, "female", function(name){
name1 = name;
age1 = this.getAge();
console.log(age1);//29 and holding, YES!
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.