Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 27.02.2024, 09:08
Интересующийся
Отправить личное сообщение для AlexandrDr Посмотреть профиль Найти все сообщения от AlexandrDr
 
Регистрация: 22.11.2018
Сообщений: 11

Помогите решить задачу
Есть следующий код:

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

Не могу понять в чем проблема, понимаю что у меня сначала исполняется синхронный код, а потом результат промиса. как исправить не понимаю пока
Ответить с цитированием
  #2 (permalink)  
Старый 27.02.2024, 12:35
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

Очевидно, в том что потерял await. Буквально "подождать".
Было "подождать this.#client.connect()", стало просто "this.#client.connect()".
Потому в первом случае он сначала коннектит, потом уж что-то делает, а во втором - он что-то делает, а потом уже когда-нибудь конектит.
__________________
29375, 35

Последний раз редактировалось Aetae, 27.02.2024 в 12:40.
Ответить с цитированием
  #3 (permalink)  
Старый 27.02.2024, 12:45
Интересующийся
Отправить личное сообщение для AlexandrDr Посмотреть профиль Найти все сообщения от AlexandrDr
 
Регистрация: 22.11.2018
Сообщений: 11

В таком случае порядок все равно неверный получается.

Выводит

done something
done something
done something
connect
done something

а нужно

connect
done something
done something
done something
done something
Изображения:
Тип файла: jpg 1.jpg (8.9 Кб, 2 просмотров)
Ответить с цитированием
  #4 (permalink)  
Старый 27.02.2024, 12:47
Интересующийся
Отправить личное сообщение для AlexandrDr Посмотреть профиль Найти все сообщения от AlexandrDr
 
Регистрация: 22.11.2018
Сообщений: 11

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


вот так вывод получается правильный, но мне сказали это костыльное решение и надо по-другому. Не могу понять как
Ответить с цитированием
  #5 (permalink)  
Старый 27.02.2024, 13:47
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

А, ну да, задачка забавная, на понимание. Утащу к себе, буду на собеседованиях давать. Решается просто.:⁠)

Вот тебе промежуточное решение:
async getClient() {
  if (!this.#client) {
    const client = new DummyClient();
    this.#client = client.connect().then(() => client);
  }
  return this.#client;
}

Оно будет работать и, в принципе, может считаться законченным, но семантически не красиво.:⁠)
__________________
29375, 35

Последний раз редактировалось Aetae, 27.02.2024 в 14:18.
Ответить с цитированием
  #6 (permalink)  
Старый 27.02.2024, 14:21
Интересующийся
Отправить личное сообщение для AlexandrDr Посмотреть профиль Найти все сообщения от AlexandrDr
 
Регистрация: 22.11.2018
Сообщений: 11

спасибо
Ответить с цитированием
  #7 (permalink)  
Старый 29.02.2024, 11:43
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,205

Предложу такой вариант...

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();
Ответить с цитированием
  #8 (permalink)  
Старый 01.03.2024, 04:48
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

ksa, лучше решения автора только тем, что гарантировано работает. На моём собесе ты бы получил маленький минус(не окончательный) за такое решение.:⁠) Никакой элегантности, левые не нужные таймеры...
__________________
29375, 35
Ответить с цитированием
  #9 (permalink)  
Старый 01.03.2024, 09:20
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,205

Сообщение от Aetae
Никакой элегантности, левые не нужные таймеры...
Я не особо спец в написании классов...
Использую "функциональное" программирование. Стараюсь тренироваться по мере возможностей.

Такой вот еще вариант сделал, но там опять есть 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();
Ответить с цитированием
  #10 (permalink)  
Старый 01.03.2024, 09:21
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,205

Aetae, покажи свой вариант полностью. Как ты сделал тот класс ApiWrapper?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите решить небольшую задачу kseosru Общие вопросы Javascript 1 24.11.2019 17:08
Помогите решить задачу fillika Events/DOM/Window 2 16.05.2019 11:39
Помогите решить задачу. Alex14 Javascript под браузер 2 29.03.2017 12:18
Помогите решить задачу! Vor_tex Общие вопросы Javascript 0 24.06.2016 13:05
Помогите решить задачу vkg Общие вопросы Javascript 1 20.02.2008 11:59