Форум программистов, компьютерный форум, киберфорум
JavaScript: React/ReactJS
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
71 / 59 / 14
Регистрация: 20.12.2013
Сообщений: 701
1

Асинхронные события в порядке очереди

09.08.2024, 22:56. Показов 354. Ответов 3
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.
В теперешнем приближении делаю запуск задачи: при нажатии кнопки
- запускаем сокетное соединение, если надо, ждем, когда нам вернется id пользователя для доступа к сокету и изменится состояние сокета
- отправляем запрос на создание созвона, ждем, когда вернется id созвона.
Не знаю как оформить наглядно, чтобы прилично и понятно выглядел. Просто бы схематично идею.
Сейчас так
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const useNewGroupCall = async (regime, setRegime, connect, status, state, httpServer) => {
    const [con, setCon] = useState(0)
    if( regime !== REGIME_STATUS.CREATE_CALL ) return
        if(con < 1)
        if( !state.idMe || status !== SOCKET_STATUS_TYPE.CONNECTED ) {
            setCon( 1 )
            connect(httpServer)
            return
        }
        if( !state.idMe || status !== SOCKET_STATUS_TYPE.CONNECTED ) return
        if(con < 2) {
            setCon( 2 )
            const url = "http://" + httpServer + `crt/call-group`
            const data = {idMe: state.idMe, title: state.title, name: state.name}
            await httpRequest(url, "POST", data, null)
        }
        if(state.idGroupCall) setRegime( REGIME_STATUS.STOPPED )
    return
}
И это мне очень не нравится.
Например не видно отдельных этапов. А с течением времени я буду смотреть на это и еще больше офигевать.
Думал может в виде цепочки промисов как-то, но не придумал. С моими знаниями усложнять боюсь будет катастрофой.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.08.2024, 22:56
Ответы с готовыми решениями:

Асинхронные очереди Glib
Всем привет! Не уверен в своём навыке понимания, решил воспользоваться библиотекой glib....

Асинхронные события уже доступны?
Внезапно обнаружил что можно у событий ставить маркер &quot;async&quot; и методы замечательно работают. ...

Переместить все элементы первой очереди (в порядке от начала к концу) в конец второй очереди
Помогите решить задачу, срочно нужно. Даны две очереди; адреса начала и конца первой равны P1 и...

Переместить все элементы первой очереди (в порядке от начала к концу) в конец второй очереди
Даны две очереди; адреса начала и конца первой равны P1 и P2, а второй – P3 и P4 (если очередь...

Переместить все элементы первой очереди (в порядке от начала к концу) в конец второй очереди
Даны две очереди; адреса начала и конца первой равны P1 и P2, а второй — P3 и P4 (если очередь...

3
молодой
 Аватар для mr_dramm
1784 / 1027 / 324
Регистрация: 17.07.2021
Сообщений: 2,076
Записей в блоге: 12
11.08.2024, 11:21 2
Лучший ответ Сообщение было отмечено AndrSlav как решение

Решение

AndrSlav, у тебя приходит много входных аргументов в кастомный хук useNewGroupCall, если даже он работает через useMemo будет вызываться на каждое изменение зависимостей. Сложно понять что будет происходить, потому что твоя функция хука асинхронная, с большой вероятностью несколько функций хука могут выполняться асинхронно(~одновременно) и там еще больше подводных камней, которые даже через отладчик трудно будет читать.

Одно из решений это декомпозиция и использование возможностей чистого js. У React одна из проблем это перерисовки, чтобы от них избавиться можно писать на чистом js.

Я написал небольшой пример, он позволяет решить перечисленные выше проблемы. Модули:
- EventEmitter - это аналог событий js
- Call - звонок
- Connection - соединение

Часть функционала который не нуждается в перерисовках написан на чистом js, который потом можно адаптировать, например, EventEmitter можно переделать под стейт менеджер проекта, js es6 модули это по сути глобальный singleton паттерн можно пользоваться их преимуществами.

Функционал примера:
- input host name - пишем сюда любую строку кроме "правильного хоста" получаем disconnect
Две кнопки для того чтобы с имитировать как будет работать при успешном и разорванном соединении
- Connect - соединение с хостом
- Disconnect - разрыв соединения
Звонок
- Сall - сначала проверяет соединение если оно уже создано звоним, если нет 3 раза пытаемся соединиться, если успешна хоть одна попытка звоним, попытки можно прервать.
- Abort - принудительный обрыв звонка

App
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import React from 'react';
import { connection, STATUS } from './connection';
import eventEmitter from './eventEmitter';
import call from './call';
function App() {
  // чтобы считать сколько неудачных попыток соедениться было
  const prevCon = React.useRef<{ host: string; count: number }>({
    host: '',
    count: 1,
  });
 
  const abort = React.useRef<(() => void) | undefined>();
  const [con, seCon] = React.useState({ status: STATUS.DISCONNECTED });
  const [callState, setCallState] = React.useState(false);
  const [host, setHost] = React.useState('');
 
  React.useEffect(() => {
    eventEmitter.on('connection', seCon);
  }, []);
  React.useEffect(() => {
    eventEmitter.on('call', setCallState);
  }, []);
 
  React.useEffect(() => {
    if (con.status == STATUS.INPROGRESS) {
      if (prevCon.current.host === host) prevCon.current.count++;
      else prevCon.current.count = 1;
      prevCon.current.host = host;
    } else {
      prevCon.current.count = 1;
    }
  }, [con, host]);
 
  const handlerCall = () => {
    setCallState(false);
    abort.current = call(host);
  };
  const handlerAbortCall = () => {
    setCallState(false);
    if(abort.current) abort.current();
  };
  const handleConect = () => {
    setCallState(false);
    connection.connect(host);
  };
  const handleDisconect = () => {
    setCallState(false);
    connection.disconnect();
  };
 
  return (
    <>
      <div>
        Host name - правильный хост только: https://example.com, остальный
        disconnected{' '}
      </div>
      <div>
        <input
          type="text"
          onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
            setHost(e.target.value)
          }
          value={host}
        />
        <button onClick={handleConect}>Connect</button>
        <button onClick={handleDisconect}>Disconnect</button>
        <button onClick={handlerCall}>Call</button>
        <button onClick={handlerAbortCall}>Abort Call</button>
      </div>
 
      <div>
        Status Connection: {con.status}{' '}
        {con.status === STATUS.INPROGRESS ? prevCon.current.count : ''}
      </div>
      <div>Status Call: {callState ? 'Call started' : 'Call failed'}</div>
    </>
  );
}
 
export default App;
call
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import { connection, STATUS } from './connection';
import eventEmitter from './eventEmitter';
 
let inprogress = false,
  abort = false;
 
// количество попыток соедениться с сервером
const tryConnect = 3;
const _call = (host: string) => {
  return new Promise(async (resolve) => {
    let con = false;
    for (let i = 0; i < tryConnect; i++) {
      if (abort) break;
      const res = await connection.connect(host);
      if (res.connection !== STATUS.CONNECTED) continue;
      con = true;
      break;
    }
    inprogress = false;
    eventEmitter.emit('call', con);
    resolve(con);
  });
};
 
const cbAbort = () => {
  abort = true;
};
 
const call = (host: string) => {
  if (inprogress) return;
  abort = false;
  inprogress = true;
 
  _call(host);
  return cbAbort;
};
export default call;
connection
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import eventEmitter from './eventEmitter';
 
export enum STATUS {
  CONNECTED = 'connected',
  DISCONNECTED = 'disconnected',
  INPROGRESS = 'inprogress',
}
 
const rightHost = 'https://example.com';
let timeout: ReturnType<typeof setTimeout> | null = null;
let host = '';
let status = STATUS.DISCONNECTED;
// обертка имитация реального соединения
export const connection = {
  connect: function (newHost: string): Promise<{ connection: STATUS }> {
    return new Promise((resolve) => {
      if (newHost == host && status === STATUS.CONNECTED) {
        return resolve({ connection: STATUS.CONNECTED });
      }
      host = newHost;
      this.notify(STATUS.INPROGRESS);
 
      if (timeout) clearTimeout(timeout);
 
      timeout = setTimeout(() => {
        timeout = null;
        let res = STATUS.DISCONNECTED;
        if (host === rightHost) res = STATUS.CONNECTED;
        this.notify(res);
        resolve({ connection: res });
      }, 5000);
    });
  },
  disconnect: async function () {
    this.notify(STATUS.DISCONNECTED);
  },
  notify: function (newStatus: STATUS) {
    status = newStatus;
    eventEmitter.emit('connection', { status });
  },
};
EventEmitter
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type Listener = (...args: any[]) => void;
 
class EventEmitter {
  private events: { [key: string]: Set<Listener> } = {};
 
  on(event: string, listener: Listener): void {
    if (!this.events[event]) {
      this.events[event] = new Set();
    }
    this.events[event].add(listener);
  }
 
  emit(event: string, ...args: any[]): void {
    if (!this.events[event]) return;
    this.events[event].forEach((listener) => {
      listener(...args);
    });
  }
}
 
export default new EventEmitter();
1
71 / 59 / 14
Регистрация: 20.12.2013
Сообщений: 701
11.08.2024, 12:41  [ТС] 3
Спасибо!
Как-то вызов setCallState в
Javascript
1
2
3
4
const handlerCall = () => {
    setCallState(false);
    abort.current = call(host);
  };
И одновременно события из промиса на изменение этого же состояния выглядят потенциально возможной гонкой.
1
молодой
 Аватар для mr_dramm
1784 / 1027 / 324
Регистрация: 17.07.2021
Сообщений: 2,076
Записей в блоге: 12
11.08.2024, 12:59 4
Цитата Сообщение от AndrSlav Посмотреть сообщение
И одновременно события из промиса на изменение этого же состояния выглядят потенциально возможной гонкой.
я этот пример особо не полировал так что если захотеть можно много чего найти, основной посыл это вынести функционал которому не нужны перерендеры в отдельные js модули не компоненты React, или написать логику в стейт менеджере , тут топорно сделан разрыв звонка просто через setCallState(false), в реальном проекте конечно нужно начинать новый звонок только после окончательного разрыва предыдущего звонка.
1
11.08.2024, 12:59
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
11.08.2024, 12:59
Помогаю со студенческими работами здесь

Есть ли способ удалить события QTimer, которые уже стоят в очереди?
Вопрос в заголовке. Можно ли их просто удалить без вызова обработчиков?

Добавление данных в порядке очереди
Доброго времени суток. Есть таблица вида: id|slot0t|slot1t|slot2t|slot3t|slot4t 1| 01| 02| 03 ...

Вывести элементы очереди в обратном порядке
Ввести из клавиатуры последовательность с n чисел (где n задается пользоватилем), внося их в...

Сортировка входящей почты в порядке очереди
Доброго времени суток. Хотелось бы решить следующую задачу, используя MS Outlook, посредством...

Изменение фона Edit в порядке очереди
На форме есть 2 элемента - Edit и Button. Каждый раз при нажатии на Button - меняется фон Edit. При...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Элементы алгоритмизации
hw_wired 28.01.2025
Основы алгоритмизации В современном мире алгоритмы играют фундаментальную роль в развитии информационных технологий и программирования. Понимание основ алгоритмизации является ключевым элементом в. . .
Человек и информация
hw_wired 28.01.2025
Введение: роль информации в познании мира В современном мире информация играет фундаментальную роль в процессе познания окружающей действительности. Она представляет собой совокупность сведений об. . .
Компьютер и информация
hw_wired 28.01.2025
Эволюция вычислительных машин История развития вычислительной техники начинается задолго до появления первых электронных устройств. Человечество всегда стремилось упростить процесс вычислений и. . .
Информационные технологии
hw_wired 28.01.2025
Введение в современные технологии работы с информацией В современном мире информационные технологии стали неотъемлемой частью практически всех сфер человеческой деятельности. Они существенно. . .
Информация вокруг нас
hw_wired 28.01.2025
Основные понятия информации В современном мире понятие информации является фундаментальным и охватывает практически все сферы человеческой деятельности. Информация представляет собой совокупность. . .
Компьютер для начинающих
hw_wired 28.01.2025
Введение в мир компьютерных технологий В современном мире информация стала одним из важнейших ресурсов человечества, определяющим развитие общества и технологий. Наша жизнь неразрывно связана с. . .
[golang] 189. Rotate Array
alhaos 28.01.2025
Повороты рукоятки, целочисленный слайс нужно сдвинуть на целое положительное число. Мне очень нравится решение на GO / / https:/ / leetcode. com/ studyplan/ top-interview-150/ package topInterview . . .
КуМир: решение задач на матрицы
bytestream 28.01.2025
КуМир представляет собой среду для обучения программированию, которая включает в себя мощные инструменты для работы с матрицами. Матрица в программировании - это двумерный массив, состоящий из. . .
КуМир: решение задач на строки
bytestream 28.01.2025
В системе программирования КуМир работа со строковыми данными является одним из важнейших аспектов создания программ. Строки представляют собой последовательности символов, заключенные в кавычки,. . .
КуМир: решение геометрических задач
bytestream 28.01.2025
Программирование геометрических задач в среде КуМир становится всё более актуальным в обучении школьников и студентов. КуМир — это разработанная в России обучающая программная среда, предназначенная. . .
КуМир, исполнитель Водолей: Задачи и решения
bytestream 28.01.2025
КуМир — это образовательная среда для обучения программированию. Она предлагает пользователям разнообразные инструменты для разработки и отладки программ, что особенно ценно для студентов и. . .
КуМир, исполнитель Чертежник: Решение задач
bytestream 28.01.2025
КуМир (Комплект Учебных МИРов) представляет собой образовательную среду для обучения основам программирования и алгоритмизации. Исполнитель Чертежник работает на координатной плоскости, где может. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru