首页 > 解决方案 > 如何创建包含异步调用的 Javascript (es5) 构造函数

问题描述

我正在尝试创建一个构造函数,其中包括对 indexedDB 或 localStorage 的调用以检索一些数据(如果存在),然后从缓存或给定(默认)数据中填充它的值。

我让它工作,但不知何故破坏了我的代码。鉴于我的编程方法是“用棍子敲打直到它起作用”,代码绝对是一团糟。所以我将问题简化为一个人为的例子,它以同样的方式失败。

删除异步函数 (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????

我在 SO 上看到使用类和承诺以及异步/等待的其他代码,但我不明白这一切是如何工作的,所以这段代码有点“老派”,对此感到抱歉。

在此示例中,您能否在新人员初始化之后立即检索人员的年龄?

标签: javascriptconstructor

解决方案


没有办法制作异步构造函数。相反,您想要做的可能是创建一个异步函数,该函数将在异步操作完成后生成您构造的对象。我会给你一个更具体的例子,但坦率地说,我不明白你的代码的异步部分试图做什么。不过,这是一个如何完成此操作的示例:

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()
})

如果您不需要支持非常旧的浏览器,我建议您使用 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()
  })

当您发布下一个 SO 问题以给出您的代码试图实现的目标的真实示例时,这将很有帮助 -getAge根据性别返回不同的结果没有多大意义:)


推荐阅读