Помогите решить задачу
Есть следующий код:
class DummyClient { async connect() { return new Promise(resolve=>{ setTimeout(()=>{ console.log('connect'); resolve() } , 2000); } ) } async doSomething() { console.log('done something') } } class ApiWrapper { #client; async getClient() { if (!this.#client) { const client = new DummyClient(); await client.connect(); this.#client = client; } return this.#client; } async doSomething() { const client = await this.getClient(); return client.doSomething(); } } const run = async()=>{ const api = new ApiWrapper(); await Promise.all([api.doSomething(), api.doSomething(), api.doSomething(), api.doSomething()]); } run(); сейчас он выводит в консоль connect done something connect done something connect done something connect done something Нужно чтоб было connect done something done something done something done something Исправлять можно только код внутри класса ApiWrapper. Я изменяю класс вот так: class ApiWrapper { #client; async getClient() { if (!this.#client) { this.#client = new DummyClient(); this.#client.connect() } return this.#client } async doSomething() { const client = await this.getClient(); await client.doSomething(); } } но в выводе у меня нарушенный порядок done something done something done something done something connect Не могу понять в чем проблема, понимаю что у меня сначала исполняется синхронный код, а потом результат промиса. как исправить не понимаю пока |
Очевидно, в том что потерял await. Буквально "подождать".
Было "подождать this.#client.connect()", стало просто "this.#client.connect()". Потому в первом случае он сначала коннектит, потом уж что-то делает, а во втором - он что-то делает, а потом уже когда-нибудь конектит. |
Вложений: 1
В таком случае порядок все равно неверный получается.
Выводит done something done something done something connect done something а нужно connect done something done something done something done something |
class ApiWrapper { #client; async getClient() { if (!this.#client) { this.#client = new DummyClient(); this.#client.connect() } return this.#client } async doSomething() { const client = await this.getClient(); setTimeout(client.doSomething, 4000) } } вот так вывод получается правильный, но мне сказали это костыльное решение и надо по-другому. Не могу понять как |
А, ну да, задачка забавная, на понимание. Утащу к себе, буду на собеседованиях давать. Решается просто.:)
Вот тебе промежуточное решение: async getClient() { if (!this.#client) { const client = new DummyClient(); this.#client = client.connect().then(() => client); } return this.#client; } Оно будет работать и, в принципе, может считаться законченным, но семантически не красиво.:) |
спасибо
|
Предложу такой вариант...
class DummyClient { connect() { return new Promise(resolve => { setTimeout(() => { console.log('connect'); resolve() } , 2000); }) } async doSomething() { console.log('done something') } } class ApiWrapper { #client; #connect = false async getClient() { this.connect = true const client = new DummyClient(); await client.connect(); this.#client = client; } async doSomething(n) { while (!this.#client) { if (!this.connect) await this.getClient(); await this.pause(100) } const v = await this.#client.doSomething(); return v } pause(t) { return new Promise(resolve => { setTimeout(resolve, t); }) } } const run = async()=>{ const api = new ApiWrapper(); await Promise.all([ api.doSomething(1), api.doSomething(2), api.doSomething(3), api.doSomething(4) ]); } run(); |
ksa, лучше решения автора только тем, что гарантировано работает. На моём собесе ты бы получил маленький минус(не окончательный) за такое решение.:) Никакой элегантности, левые не нужные таймеры...
|
Цитата:
Использую "функциональное" программирование. Стараюсь тренироваться по мере возможностей. Такой вот еще вариант сделал, но там опять есть pause. class DummyClient { async connect() { return new Promise(resolve=>{ setTimeout(()=>{ console.log('connect'); resolve() } , 2000); } ) } async doSomething() { console.log('done something') } } class ApiWrapper extends DummyClient { #connect = null async doSomething() { while (!this.#connect) { if (this.#connect == null) { this.#connect = false await this.connect() this.#connect = true } await this.pause(100) } await super.doSomething() } pause(t) { return new Promise(res => setTimeout(res, t)) } } const run = async () => { const api = new ApiWrapper(); await Promise.all([ api.doSomething(), api.doSomething(), api.doSomething(), api.doSomething() ]); } run(); |
Aetae, покажи свой вариант полностью. Как ты сделал тот класс ApiWrapper?
|
Часовой пояс GMT +3, время: 15:12. |