在初始化新类之后,ES6 Class在继续之前等待请求?

时间:2017-10-16 21:38:25

标签: javascript node.js class ecmascript-6

我正在尝试创建一个像这样的新类:

const request = require("request");

class Person {
    constructor(personName) {
        request(`http://personapi.com/name/${personName}`, (err, res, body) => {
            body = JSON.parse(body);
            this.name = body.name;
            this.age = body.age;
            this.gender = body.gender;
        }
    }
}

let person = new Person("Donald Trump");
console.log(person.name);

执行上述操作不起作用,因为它会创建一个没有属性的新人,因为请求尚未加载。如果我这样做:

let person = new Person("Donald Trump");
setTimeout(() => {
    console.log(person.name);
}, 1000);

工作正常。我知道这是因为它是异步的。在请求完成之前,如何确保let person未实际设置?不要担心代码阻塞。

2 个答案:

答案 0 :(得分:3)

也许只是在实例化Person之前做一个请求:

const request = require("request");

class Person {
    constructor(obj) {
            this.name = obj.name;
            this.age = obj.age;
            this.gender = obj.gender;
    }
}

let person;

request(`http://personapi.com/name/${personName}`, (err, res, body) => {
    body = JSON.parse(body);
    person = new Person(body);
});

答案 1 :(得分:1)

我建议将承诺存储在财产中:

const request = require("request");

class Person {
    constructor(personName) {
        this.ready = 
          request(`http://personapi.com/name/${personName}`, (err, res, body) => {
              body = JSON.parse(body);
              this.name = body.name;
              this.age = body.age;
              this.gender = body.gender;
          });
    }
}

let person = new Person("Donald Trump");
person.ready.then(_ => console.log(person.name));

虽然看起来有点hacky。另一个看起来更好的选项,也将人员相关逻辑封装在Person类中:

const request = require("request");

class Person {
    constructor({name, age, gender}) {
      this.name   = name;
      this.age    = age;
      this.gender = gender;
    }

    static fromName(name) {
      return request(`http://personapi.com/name/${personName}`)
        .then(resp => resp.json())
        .then(body => new this(body));
    }
}

Person
  .fromName("Donald Trump")
  .then(person => console.log(person.name);