【发布时间】:2022-11-21 18:50:47
【问题描述】:
我发现了一个有趣的问题(不是真正的任务):
class Client {
async connect() {
return new Promise(resolve => {
setTimeout(() => {
console.log('connect');
resolve()
}, 2000);
})
}
async request() {
console.log('done something')
}
}
class Api {
#client;
async getClient() {
if (!this.#client) {
const client = new Client();
await client.connect();
this.#client = client;
}
return this.#client;
}
async request() {
const client = await this.getClient();
return client.request();
}
}
const run = async () => {
const api = new Api();
await Promise.all([api.request(), api.request(), api.request(), api.request()]);
}
run();
它会输出这个:
connect
request completed
connect
request completed
connect
request completed
connect
request completed
显然,我们需要等待初始连接,然后再解决其他请求,所以输出将是这样的:
connect
request completed
request completed
request completed
request completed
我的工作解决方案:
class Client {
async connect() {
return new Promise(resolve => {
setTimeout(() => {
console.log('connect');
resolve()
}, 2000);
})
}
async request() {
console.log('request completed')
}
}
class Api {
#connecting = false;
#client;
#queue = [];
async getClient() {
if (!this.#client && !this.#connecting) {
this.#connecting = true;
const client = new Client();
await client.connect();
this.#connecting = false;
this.#client = client;
this.resolveQueue(client)
}
return this.#client;
}
async resolveQueue(client) {
await Promise.all(this.#queue.map(task => task(client)))
}
async request() {
const client = await this.getClient();
if (client) {
return client.request();
} else {
this.#queue.push(async (client) => client.request());
}
}
}
const run = async () => {
const api = new Api();
await Promise.all([api.request(), api.request(), api.request(), api.request()]);
}
run();
但似乎应该有更清晰/更简单的方法来做到这一点,因为我增加了很多层次和复杂性。另外,我认为这里的目标是添加尽可能少的更改,保持代码结构不变,我也试图实现这一点。在现实世界的情况下,我可能会完全重写它并使其更加冗长。
【问题讨论】:
标签: javascript promise