С помощью раньше упомянутого sharedArrayBuffer. Есть такая замечательная вещь как Atomics, которая одним из методов, а именно wait, позволяет усыпить весь поток в ожидании изменений в буфере.
Уууу... ну поток блокируется бесконечным циклом хорошо :) можно просто сделать while(waitForReply) какой-нибудь и он должен подвешать поток. А внутри цикла как-то проверять новые сообщения от основного потока в надежде что придет то самое сообщение и разблочит поток. Не знаю даже как еще можно "приостановить" поток. Но сомнительно что бесконечные циклы в фоне хорошая идея. И не совсем понятно как изнутри цикла который заблокировал поток будут выполняться те же слушатели для postmessage. По идее никак если поток блокирован.Такая себе идея получается. Еще думал про какую-нибудь shared memory между основным потоком и воркером чтобы сделать операцию синхронной. Можно было бы в эту сторону покопать. cliff hanger это ты конечно хорошо придумал, заставляет хотя бы немножко подумать над решением, что лучше чем просто его сразу узнать с точки зрения получения информации
@@qwiting но ведь новая макротаска будет запускаться на другом стеке вызова уже и на новом тике ивент лупа, а блокирующая функция так и должна оставаться на том же тике. Без примера кода я слабо представляю как это должно работать.
@@qwiting потому что если в коде будет try catch то он работать не будет так как он связывается по тактам ивент лупа. И есть пример кода? Какой-то пруф о консепт. Я не понимаю как таймаутами можно имитировать синхронный вызов. Ну то есть у нас тайм-аут на третьей строке и как заставить его выполниться раньше чем четвертая строка этой же функции которая уже попала в стек вызова
Можно топорно заблокировать бесконечным циклом с проверкой (прощай CPU). Вообще как то пробовал делать что то похожее на sleep при синхронном исполнении.
@@xxxxPomaHxxxx function dieLoop() { return Promise.resolve().then(dieLoop)} Эта функция начнет выполняться в стеке вызовов. Когда выполнится весь синхронный код, то начнут выполняться микротаски. Зарезолвится промис, потом здесь же снова вызовется функция и по кругу. Таким образом мы не перейдем на следующий шаг эвентлупа, а навеки застрянем на текущем шагу
Вероятно в итоге все равно потребуется обменяться SharedArrayBuffer и повесить мьютекс на функцию работающую с DOM. Если код из WW хочет получить offsetWidth, а затем, основываясь на этом значении что-то сделать с DOM - эта операция должна быть атомарной (что, если другой поток поменяет ширину элемента в промежутке между обменом сообщениями). Главный поток гарантирует нам атомарность при работе с DOM, а рассмотренном случае мы ее теряем.
@@bubblesort6368 В контексте задачи Ильи у нас один общий ресурс по сути (DOM), поэтому дедлоку неоткуда взяться. Один поток ждет другой, не заняв ни один из общих ресурсов. Насколько я понимаю/помню видео, может подзабылось уже)
@@АлександрПрозоров-ъ9ь ну если захватывать весь дом а не ноды отдельно то дедлоков не будет. Я полагал вы хотите лочить более точечно на уровне поддеревьев и узлов. Там две корутины могут циклически завязаться на два элемента дома
Если потоки могут обмениваться объектами, значит воркер может просто запросить объект, поставить блокировку на изменение этого объекта в основном потоке, сделать всё что нужно и вернуть объект в основной поток сняв блокировку с него. Зачем блокировать эвентлуп?
@@sergeyvp блокувати треба тому, що операції з DOM синхронні і це дає певні гарантії, на які може очікувати код, який виконується в service worker. Потрібна консистентність
@@d3i0 ничем не поможет. Просто синтаксис другой будет и все) типа вместо while вы будете в for .. of крутить бесконечный список построенный на генераторах
. while(true) // ждём ответа Это анти-паттерн в основном потоке , но в воркерах, почему бы и нет? Конечно же с точки зрения cpu неэффективно и батарейку будет жрать только в путь, но кого это волнует в наше время))
Сделать бесконечный цикл, который будет проверять пришло ли ответное сообщение, только тогда надо будет использовать этот sharedArrayBuffer объект. Хз, мне кажется может получиться
Спустя пару минут гугления, нашел вот такую штуку: Atomics.wait(), которая позволяет синхронно подождать какой то таймаут. Т.е. мы можем "уснуть" на какое то время, и потом проверить, а не пришло ли уже значение из главного треда. Звучит как рабочий вариант. Ну и еще из глупого решения - сделать бесконечный while, который будет грузить cpu.
Оно как раз таки вместе с бесконечным while и собирается, чтобы дождаться обработки запроса с текущего потока, типа: while(Atomics.wait(int32arr,0,queueToken) !== "ok");
Илья, спасибо вам большое за ваш вклад в сообщество! Вы прекрасный человек и специалист! Здоровья вам и мира этому миру!
Только сегодня вспоминал Вас, давно видео не было, начал волноваться... Берегите себя.
Очень актуальная тема. Жду продолжения. Как заблокировать эвентлуп, хотя бы одним из способов, понятно, интересно как его потом разблокировать.
С помощью раньше упомянутого sharedArrayBuffer. Есть такая замечательная вещь как Atomics, которая одним из методов, а именно wait, позволяет усыпить весь поток в ожидании изменений в буфере.
За "покращену" архітектуру лайк )
Очень круто, спасибо за видео!
Берегите себя Илья!
Занятно. Спасибо.
❤️
Если я не ошибаюсь, запуск скриптов в Worker'е с проксированием DOM умела ещё AMP
А куда идти за пирожком?)
Подумал про последовательные вызовы queueMicrotask()
Уууу... ну поток блокируется бесконечным циклом хорошо :) можно просто сделать while(waitForReply) какой-нибудь и он должен подвешать поток. А внутри цикла как-то проверять новые сообщения от основного потока в надежде что придет то самое сообщение и разблочит поток. Не знаю даже как еще можно "приостановить" поток. Но сомнительно что бесконечные циклы в фоне хорошая идея. И не совсем понятно как изнутри цикла который заблокировал поток будут выполняться те же слушатели для postmessage. По идее никак если поток блокирован.Такая себе идея получается.
Еще думал про какую-нибудь shared memory между основным потоком и воркером чтобы сделать операцию синхронной. Можно было бы в эту сторону покопать.
cliff hanger это ты конечно хорошо придумал, заставляет хотя бы немножко подумать над решением, что лучше чем просто его сразу узнать с точки зрения получения информации
А если в функцию добавить setTimeout которая вызывает эту же функцию до тех пор, пока операция не завершилась
И плодить макротаски?
@@bubblesort6368 ну да
@@qwiting но ведь новая макротаска будет запускаться на другом стеке вызова уже и на новом тике ивент лупа, а блокирующая функция так и должна оставаться на том же тике. Без примера кода я слабо представляю как это должно работать.
@@bubblesort6368 а зачем оставаться на том же тике?
@@qwiting потому что если в коде будет try catch то он работать не будет так как он связывается по тактам ивент лупа. И есть пример кода? Какой-то пруф о консепт. Я не понимаю как таймаутами можно имитировать синхронный вызов. Ну то есть у нас тайм-аут на третьей строке и как заставить его выполниться раньше чем четвертая строка этой же функции которая уже попала в стек вызова
Можно топорно заблокировать бесконечным циклом с проверкой (прощай CPU). Вообще как то пробовал делать что то похожее на sleep при синхронном исполнении.
А если что-то пойдёт не так ) будет бобо
@@ВитяПолторацкий-ш3ы ну это ясно что такое решение не годится :) Просто нужно было озвучить этот вариант.
Как заблокировать эвентлуп? Через микротаски!
Ты так максимум заблокируешь переход на следующую очередь, а не синхронный код.
@@xxxxPomaHxxxx function dieLoop() { return Promise.resolve().then(dieLoop)}
Эта функция начнет выполняться в стеке вызовов. Когда выполнится весь синхронный код, то начнут выполняться микротаски. Зарезолвится промис, потом здесь же снова вызовется функция и по кругу. Таким образом мы не перейдем на следующий шаг эвентлупа, а навеки застрянем на текущем шагу
@@isfland А нам нужно паузить посреди синхронного кода, ваш вариант не поможет в ситуации в видео.
@@isfland зачем тут микротаски, если также заблокировать можно и обычным стеком? Псевдокод while (waitFor)
@@vladislavstepanov7591 согласен, микротаски оверкилл
while c pointer?
Яка ситуація у Харкові? Привіт з Франківська)
Стабильно. Прилеты.
Вероятно в итоге все равно потребуется обменяться SharedArrayBuffer и повесить мьютекс на функцию работающую с DOM. Если код из WW хочет получить offsetWidth, а затем, основываясь на этом значении что-то сделать с DOM - эта операция должна быть атомарной (что, если другой поток поменяет ширину элемента в промежутке между обменом сообщениями). Главный поток гарантирует нам атомарность при работе с DOM, а рассмотренном случае мы ее теряем.
И привет дедлоки) ну вообще не удивительно, что браузеры до сих пор однопоточно с домом работают
@@bubblesort6368 В контексте задачи Ильи у нас один общий ресурс по сути (DOM), поэтому дедлоку неоткуда взяться. Один поток ждет другой, не заняв ни один из общих ресурсов. Насколько я понимаю/помню видео, может подзабылось уже)
@@АлександрПрозоров-ъ9ь ну если захватывать весь дом а не ноды отдельно то дедлоков не будет. Я полагал вы хотите лочить более точечно на уровне поддеревьев и узлов. Там две корутины могут циклически завязаться на два элемента дома
Похорошел кстати
интригант )))
alert/prompt можливо блокуe чергу. Iлья, дякую за вiдео
Очень умный парень, очень много делает для всех, надеюсь ума хватит, чтоб не загребли и не отправили в мясорубку
Если потоки могут обмениваться объектами, значит воркер может просто запросить объект, поставить блокировку на изменение этого объекта в основном потоке, сделать всё что нужно и вернуть объект в основной поток сняв блокировку с него. Зачем блокировать эвентлуп?
А где я говорил что обмениваются объектами? Я чётко расскащал что там клонирование идёт :)
@@JavaScriptNinja 4:07 Склонировали объект и на источник поставили блок, затем внесли изменения в клон и заменили им источник. Зачем блокировать луп?
@@sergeyvp блокувати треба тому, що операції з DOM синхронні і це дає певні гарантії, на які може очікувати код, який виконується в service worker. Потрібна консистентність
@@yevhenbadorov7961 Если блокировать то зачем распараллеливать? Параллельное исполнение как раз нужно чтобы не было никаких блокировок.
@@sergeyvp потому что код, написанный НЕ НАМИ понятия не имеет что условный el.offsetHeight АСИНХРОННЫЙ, ну и блоков таких нет )
Треба м'ютекс реалізований через shared array buffer, як Тимур реалізовував тут th-cam.com/video/JNLrITevhRI/w-d-xo.html
Кроме генераторов в джс ничего нет пока , чтоб это сделать адекватно
Крутить while в котором проверять что в SharedArrayBuffer появилось значение, которое записывать из основного потока?
как вариант крутить while внутри генератора
@@mykhailochernov1222 что-то я не понял как это поможет, можете объяснить?
@@d3i0 ничем не поможет. Просто синтаксис другой будет и все) типа вместо while вы будете в for .. of крутить бесконечный список построенный на генераторах
ответ наверное генераторы?
так как это единственное что приходит на ум
да, yield
. while(true) // ждём ответа
Это анти-паттерн в основном потоке , но в воркерах, почему бы и нет? Конечно же с точки зрения cpu неэффективно и батарейку будет жрать только в путь, но кого это волнует в наше время))
До конца не додумал мысль, но вариант такой: под капотом async у нас promise и генераторы. Поэтому возможно что-то похожее.
yield
Запустить вызов микротасков бесконечно в зависимости от флага. Потом когда получили обраный ответ снять флаг.
Сделать бесконечный цикл, который будет проверять пришло ли ответное сообщение, только тогда надо будет использовать этот sharedArrayBuffer объект. Хз, мне кажется может получиться
Сорян, но произношение слов width, height, query - боль.
Норм произношение. Я бы легко понял что он имел ввиду не глядя в видео и носитель eng поймёт
это уроки не по англискому
Спасибо что контент снова на русском. Астрологи предсказывают увеличение аудитории в 10 раз
А никто не обещал контент только на украинском. Контент который зеркалится с патреона будет на русском
@@JavaScriptNinja давно уже смотрю на украинском, 6 понятливее чем английский индуса.
Спустя пару минут гугления, нашел вот такую штуку: Atomics.wait(), которая позволяет синхронно подождать какой то таймаут. Т.е. мы можем "уснуть" на какое то время, и потом проверить, а не пришло ли уже значение из главного треда. Звучит как рабочий вариант. Ну и еще из глупого решения - сделать бесконечный while, который будет грузить cpu.
И уже после этого я услышал "но только пожалуйста попробуйте не гуглить"
Оно как раз таки вместе с бесконечным while и собирается, чтобы дождаться обработки запроса с текущего потока, типа:
while(Atomics.wait(int32arr,0,queueToken) !== "ok");
круто, не слышал про атомикс раньше