Як зовні перервати виконання асинхронної функції

> Необхідність перервати виконання може потрапити на довгий sleep і довгу мережеву операцію

Не може, в цьому суть Ноди (або навіть libev), яка все IO-операції делегує в інший потік, в "обчислювальному" потоці Ноди, по-суті, перебувають тільки калбекі (явні, в тому числі від таймерів, і неявні).

> Постійна перевірка прапора перед кожним await вбиває всю елегантність рішення

По-іншому не вийде, тому як ніхто інший не зможе перевірити необхідність зупинки, Нода (або навіть V8) однопоточні, і в довгі обчислення "безперервної" функції не зможе втрутитися навіть обробник подій (наприклад, по сигналу від IO або сусіднього Воркер).

Якщо потрібні довгі, але перериваються обчислення, відправляйте їх в Воркер (за допомогою модуля cluster, наприклад), і при необхідності вбивайте Воркер (пересоздавал).

Dark Hole. спробуйте і на C ++, щоб зрозуміти, що таке багатопоточний програмування, мютекси, критичні секції, семафори. Потім ще спробуйте Ерланг або Смаллтолк, спробуйте осягнути інші парадигми багатозадачності, акторную модель, наприклад. І повертайтеся програмувати на Ноде з любов'ю, а не обзиваючи її милицями тільки тому, що колись якийсь школяр так сказав, не зумівши в своїй голові вмістити більше двох підходів до вирішення однієї абстрактної проблеми :).

napa3um. ви якусь нісенітницю говорите, що означає "не може", в прикладі вище sleep реалізований через таймер + промис. Тепер уявіть що в async функції ви пішли спати на 60 секунд, а в основному потоці (або з іншої async функції) вам треба перервати виконання async функції і почистити сміття?

Михайло Юрійович. відповів уже на ваше запитання. Якщо функція щось безперервно обчислює, то зупинити її з того ж потоку не вийде, тому що в ньому працює тільки ця обчислює функція (навіть калбекі на IO-події або події таймера не зможуть виконатися, якщо функція не викликає всередині себе ніяких асинхронних операцій). В цьому випадку єдиний спосіб переривати обчислення - винести їх в Воркер і прибивати Воркер при необхідності. Якщо ж функція нічого не обчислює, а лише чекає події від таймера (в Ноде таймери не заморожує потік, а лише викликають калбекі в зазначений час), то щоб скасувати виконання цієї чекає функції досить знищити таймер викликом clearTimeout. Не соромтеся чогось недостатньо розуміють, асинхронна модель виконання - не така вже й проста тема і вимагає не тільки теорії, але і практики, щоб "осяятися розумінням" :).

napa3um. спасибі що прояснили! тепер то я точно осяяний. Тут я бачу не варто продовжувати з вами дискусію :) хоча може осяяти мене, і запропонуйте гарне рішення як перервати асинхронну функцію в якій 5 сліпів і між ними 5 tcp з'єднань. Тільки, будь ласка, не скачуйтеся до своїх Воркер і важким обчислень, про які мова власне і не йде

"Красиве рішення як перервати асинхронну функцію в якій 5 сліпів і між ними 5 tcp з'єднань" - знищити таймер, який створює ваш "сліп" (зберігати таймер, який створюється в snooze, в одній і тій же зовнішньої змінної, асоційованої з конкретною функцією, яку ви хочете "переривати", і потім викликати clearTimeout, коли захочеться функцію перервати). Якщо не хочете повернути Воркер.

в такому випадку у Вас з таким в корені неправильним підходом повинен бути супер комп'ютер і cluster Вам на допомогу.
Міняйте підхід, робіть за принципом Event Loop (як nginx робить, як це в основі node), тоді не потрібні будуть sleep, а асинхронний Worker сам буде отримувати потрібні сигнали. 10k станів (Не операцій) можна обслуговувати за допомогою декількох Workers, без шкоди продуктивності заліза. Не треба забувати, що в реальності виконується лише одна операція на процесор, потрібно лише відслідковувати стану і ніхто не заважає підмішувати в стан сигнал переривання, сигнал зайти через сотню-другу loop-ів і тп. Придивіться до методики "реактивного програмування" (RxJS). Заодно вирішите проблеми, про які поки ще не встигли задуматися - організація розподіленого "читати-писати": щоб забезпечити даними 10к процесів, доведеться "витягувати" дані в потік, а потім з потоку "висмикувати" дані для кожного з процесів. Неважко здогадатися, що кожен процес повинен щось брати десь і генерувати якісь дані, які теж кудись треба складати. Для цього ж не треба ще 2 × 10k процесів?

У Вас немає "витонченості рішення", тому як немає рішення як такого :(

Щоб не зламати мізки про Rx - ось шапаргалка

Ще 25 назад років викладачі програмування говорили: використання прямих переходів і функції noop (sleep) - означає лише те, що ти ніхрена програмувати не вмієш. А в першу чергу - правильно ставити завдання і правильно вибирати спосіб вирішення.

ви можете і далі намагатися розповідати свій досвід на пхп, вчити і наставляти інших, тільки будь ласка, якщо у вас немає рішення по темі питання (перервати async функцію ззовні) - пройдіть повз, не показуйте свою некомпетентність

до прочитання: корутіни, зелені потоки, ось приклад з python / gevent www.gevent.org/gevent.html (метод kill)
скасування (cancel / kill / throw) реалізується в тому чи іншому вигляді у всіх нормальних бібліотеках, наприклад в тому ж bluebird: bluebirdjs.com/docs/api/cancellation.html - але це милицю, тому що ми повинні задавати cancel-callback для кожної цікавить нас операції

відповідаючи на своє ж запитання з першого поста - на поточний момент в спікся JS немає механізму скасування async функції
але вихід є, ми швидше за все зарелізім в опенсорс свою бібліотеку для Ноди (поверх fibers / libcoro)