【问题标题】:Call JavaScript class method synchronously同步调用 JavaScript 类方法
【发布时间】:2019-02-12 10:58:59
【问题描述】:

我正在用 JavaScript 构建一个包,它有两个功能:initsendData

class Client {
   init() {
     return axios.post(this.baseUrl).then((response) => {
       this.token = response.data.token
     })
   }

   sendData() {
     return axios.post(this.baseUrl, {token: this.token})
   }
}

init 方法需要在 sendData 方法之前调用,因为这会返回一个令牌。有没有办法在调用sendData方法之前等待调用init方法?

【问题讨论】:

  • 你需要使init函数返回promise(也根据代码风格进行异步)并让它与sendData链接。由于 axios 方法是异步的,因此无法等待它以同步方式完成。

标签: javascript async-await es6-promise


【解决方案1】:

您是否需要 API 的使用者来执行此操作?

// within an async function
const client = new Client();
await client.init();
await client.sendDate();

// or anywhere just using promises
const client = new Client();
client.init().then(() => client.sendDate());

还是 API 本身?

// definition
class Client {
   async init() {
     const response = await axios.post(this.baseUrl);
     this.token = response.data.token;
   }

   async sendData() {
     await this.init(); // call init before sending data
     return axios.post(this.baseUrl, {token: this.token})
   }
}

// usage somewhere in an async function
const client = new Client();
client.sendDate() // calls init, then sends the data

如果令牌没有改变,也许可以删除多余的调用?

class Client {
   async init() {
     const response = await axios.post(this.baseUrl);
     this.token = response.data.token;
   }

   async sendData() {
     if (!this.token) { // now you'll only call init for missing token
       await this.init();
     }
     return axios.post(this.baseUrl, {token: this.token})
   }
}

// usage somewhere in an async function
const client = new Client();
await client.sendDate(); // calls init (only the first time), then sends the data

请注意,promise 返回函数本质上是异步的,因此无法以同步方式获取它们的结果。但是,我们可以使用 async/await 编写异步代码,使其在语法上看起来(几乎)与同步版本相同。

【讨论】:

  • 这是一个客户端 SDK,因此 API 的使用者需要这样做
  • @NathanDunn 给了你几个选择,希望对你有帮助
  • 非常感谢! :) @nem035
【解决方案2】:

异步初始化是工厂模式的一个很好的用例。与其在构造类之后进行异步工作,不如在构造之前进行并保持构造函数同步。在我看来,进行简单赋值的同步构造函数的“气味”最少,并且最容易测试。

class Client {

   constructor(baseUrl, token) {
      this.baseUrl = baseUrl;
      this.token = token;
   }

   async create(baseUrl) {
     const response = await axios.post(baseUrl);
     return new Client(baseUrl, response.data.token);
   }

   async sendData() {
     return axios.post(this.baseUrl, {token: this.token})
   }
}

...

const client = await Client.create('http://foo.com');
const response = await client.sendData();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 2010-11-11
    相关资源
    最近更新 更多