Как стать автором
Обновить

AbortController: Варианты применения для эффективного управления асинхронными операциями

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров16K
Всего голосов 15: ↑15 и ↓0+15
Комментарии30

Комментарии 30

"можно прерывать выполнение асинхронных задач и предотвращать нежелательные побочные эффекты от выполнения задач, которые уже неактуальны."

Полагаю, что синхронные или нет бывают события, а не задачи.

Применительно к задачам можно выделить события их начала и окончания.

Поэтому , Вы не "прерываете асинхронные задачи", а используете синхронные события,так как создаете их по таймеру, т.е. c известным моментом их наступления.

Да нет, речь именно об асинхронных задачах. Точного определения не скажу, но всем кроме вас почему-то понятно о чём речь.


И задачи тут именно что прерываются, поскольку прекращают своё исполнение при получении того самого синхронного события.

Не хотел заниматься ликбезом, но придется.

Асинхронность означает, что мы не знаем точного времени наступления событий и поэтому не может их синхронизировать между собой.

Задачи - это процессы которые длятся во времени, а события - это начало и окончание выполнения задачи.

Синхронность или асинхронность относится к событиям т е к моментам времени, а не к отрезкам времени.

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

Не надо путать кислое с зеленым.

Синхронность или асинхронность относится к событиям т е к моментам времени, а не к отрезкам времени.

Синхронность или асинхронность — это многозначный термин, точное значение которого меняется от объекта к которому он приложен.


О каких таких моментах времени идёт речь, например, в синхронном плавании? Или при синхронизации часов? А в синхронных генераторах?


А при синхронизации данных? Тут, между прочим, не то что событий, тут времени нету!


Конкретно в программировании под асинхронностью, обычно, понимают вот эту концепцию:


Асинхронный ввод-вывод, в информатике, является способ осуществления операций ввода/вывода, позволяющий проводить другую обработку, до того как операция ввода/вывода завершена — https://ru.wikipedia.org/wiki/Асинхронность

Asynchrony (computer programming), the occurrence of events independent of the main program flow, and ways to deal with such events — https://en.wikipedia.org/wiki/Asynchrony

Синхронность или нет это всегда события, а не процесс.

синхронное плавание - т е пловцы совершают некоторые действия - события одновременно для наблюдателя. иначе сказать, мы полагаем, что действия одного пловца однозначно и одномоментно порождают действия другого.

Синхронный генератор, это значит , что момент перехода сигнала генератора ноль однозначно определяется моментом аналогичного перехода сигнала синхронизирующего генератора.

Асинхронный ввод-вывод означает, что мы априори не знаем в какой момент времени придут данные или их надо передать, т.е. не знаем момента наступления события.

т е синхронность и асинхронность всегда связаны с моментом времени.

И это всегда, применительно к предметной области, однозначно.

Многозначность там, где присутствует поверхностное понимание предмета.

Неоднозначность в понятиях приводит к путанице в мыслях.

Только вот определения этих терминов не совпадают с тем что вы назвали:


Синхронное плавание — водный вид спорта, связанный с выполнением в воде различных фигур под музыку.

Синхронный генератор — это генератор, частота вращения ротора которого равна частоте вращения электромагнитого поля в воздушном зазоре.

Понимаете? Хоть вы и "вывели" их в своих рассуждениях из моментов времени, напрямую в общепринятых определениях моменты времени никак не участвуют.


Так почему вы отказываете программистам в праве аналогично "вывести" определение асинхронной задачи?


PS всё ещё жду от вас объяснение синхронизации данных


Неоднозначность в понятиях приводит к путанице в мыслях.

Асинхронные задачи определены вполне однозначно, запутались в мыслях тут только вы

Что вы хотели сказать вашей ссылкой?


Я вот, например, вижу там использование термина "асинхронное вычисление", который является синонимом для "асинхронной задачи".

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

Любая задача, если в ней нет ошибок, возвращает управление в момент своего завершения.

Но даже если взять Ваше определение, то Вы рассматриваете два события:

завершение задачи и возврат управления.

Т.е. синхронность или асинхронность всегда связана с событиями, а не с процессом.

В программировании асинхронность это не обязательно совпадение во времени двух событий.

Например ввод с клавиатуры человеком.

Для программирования данное событие будет асинхронным, если мы априори не знаем, когда человек нажмет на клавишу.

Но событие будет синхронным, если мы знаем что ровно в 10 часов нажмет на клавишу.

Т е в данном случае событие становится синхронным со временем.

Если берутся два события, то мы синхронизируем одно относительно другого.

Т е зная, что одно событие произошло, мы может точно сказать когда произойдет другое. Мера понятия "точно" - это показание таймера.

поддерживаю
печально, что многие фронтенд разработчики не понимают смысл написанного вами

AbortController это также событие, которое может быть порождено в любой момент, в тч в текущем цикле выполнения

Крайне важно это учитывать, например отслеживать аборт до выполнения логики: signal.throwIfAborted()

также на каждом шаге, на котором можно прерывать логику (если быть точнее перед шагом в логике) надо делать проверку на аборт

Ну и не забывать, что асинхронные события имеют свойства гонки

Потому всегда нужно держать в голове, что у нас не задачи, которые прерываются - а разные потоки событие, порождающие эффекты (тобиш события)

Интересная статья показывающая варианты использования отмены промисов. Единственное замечание - это то что если промис отменить то node.js(предполагаю что в браузере анологичное поведение) удалит промис из call stack и еще и удалит ссылку на выполнение. Это значит, что мы экономим память приложению тк явно показываем GC что данный блок кода уже неактуален

Не совсем так. Отменённый промис — это просто разновидность завершённого с ошибкой, тип ошибки — DOMException (потому что AbortController — это не часть языка, а часть HTML API). Все эффекты вроде удаления ссылок — это просто следствия перехода промиса в завершённое состояние.

const controller = new AbortController();

// После создания экземпляра AbortController, можно получить экземпляр AbortSignal, используя свойство signal:

const signal = controller.signal;

// Имитация отмены запроса через 3 секунды

setTimeout(() => {
  controller.abort();
}, 3000);

fetch('https://api.example.com/data', { signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Fetch request aborted');
    } else {
      console.error('Fetch request failed:', error);
    }
  });

Лучше всё же как-то так:

const fiber = new Fiber( ()=> console.log( fetch('https://api.example.com/data').json() ) )
setTimeout( ()=> fiber.destructor(), 3000 )
fiber.async()

Не надо учить детей своим вредным привычкам.

Функцию fetch ваша Fiber подменяет? Если нет, то код не эквивалентный. Если да — то не надо учить детей вредным привычкам, стандартные функции должны работать в соответствии со стандартом, а не вашими хотелками.

А это и не глобальная функция. Делать выводы, не разобравшись в контексте, тоже дурная привычка.

У вас в коде я не вижу никаких импортов.


Показывать детям код, в котором fetch является непонятно чем — дурной тон, они же скопируют и он у них не будет работать.

Примечательно то, что запрос на клиенте мы отменили, а на сервере это никак не отразилось. Он все равно потратит время и ресурсы на то, чтобы обработать запрос до конца.

От сервера зависит.

а как серверу правильно на это реагировать?

Точно так же — прерывать обработку запроса (при условии, что результат не нужен ему самому)

то есть условно в колбеке отмены фронт должен еще один запрос слать о том, что ему больше результат не нужен? или как сервер поймет, что AbortController сработал?

Клиент обрывает соединение, и сервер понимает что ответ на запрос никому не нужен.

вообще обрывается конекшн

еще бывает 499 статус для оборванных конекшнов, но это уже респонс статус

на бекенде я всегда прерывал логику при обрыве конекшнов, на случай где такое нужно

в большинстве кейсов где вытащить из БД и отразить в JSON, json просто улетит в трубу

Используйте AbortController только тогда, когда действительно нужно отменять асинхронные операции. В некоторых случаях альтернативные подходы могут быть более подходящими (например, игнорирование результата, если он неактуален).

Можно подробнее? Что отсылает контроллер на бэк, чтобы он там перестал выполнять операции ? Как это может обработать бэк? Я не смог такого нагуглить и для себя пришел к выводу, что этот контроллер как раз просто говорит браузеру "забудь про этот запрос", но под капотом все работает как обычно.

Отмена запроса приводит к сбросу соединения, что в свою очередь может поймать уже сервер.


Как это обрабатывать серверу — дело сервера, но основные СУБД тоже умеют отменять запросы.

извините, но я никак не могу этого нагуглить. поделитесь ссылкой, как обрабатывать сброс соединения браузером?

Ну, к примеру, в ASP.NET Core за отмену запроса отвечает свойство (ControllerBase).HttpContext.RequestAborted, оно имеет тип CancellationToken (аналог AbortSignal, с которого AbortSignal и писался) и его можно передавать по цепочке дальше.

Да, выше уже прочитал, хабр модерирует комменты с задержкой в двое суток.

Это вам ещё повезло, на VC меня вообще забанили за первый же комментарий по делу.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории