Имя: Пароль:
1C
 
Своя асинхронная функция
↓ (Волшебник 28.05.2024 07:43)
0 TrueBuild
 
23.05.24
12:16
Почитал документацию, но нигде не нашел упоминания, что нельзя делать свои асинхронные функции. Однако и платформа не ругается, когда я пытаюсь сделать свои асинхронные функции, но при этом и отрабатывает не так, как надо.
Подскажите, свои асинхронные функции не поддерживаются или у меня ошибка в коде?

Подразумевается, что после запуска процедуры Команда1, асинхронно начнет выполняться функция Пауза(), в переменную Результат запишется обещание. Далее без ожидания завершения сразу появиться Предупреждение. А уже после закрытия предупреждения в переменную Ответ запишется 5 после того, как Пауза() отработает.

Но в итоге код Результат = Пауза(5); выполняется синхронно и сразу ждет выполнения функции.

&НаКлиенте
Асинх Процедура Команда1(Команда)
	
	Результат = Пауза(5);
	Ждать ПредупреждениеАсинх("Сейчас будем ждать");
	Ответ = Ждать Результат;
	Сообщить("Готово");
	
КонецПроцедуры

&НаКлиенте
Асинх Функция Пауза(Секунд)
	
	ДатаВыхода = ТекущаяДата() + Секунд;
	Пока ТекущаяДата() < ДатаВыхода Цикл
		ОбработкаПрерыванияПользователя();
	КонецЦикла;
	
	Возврат Секунд;
	
КонецФункции
1 Мультук
 
23.05.24
12:29
(0)
Имхо вот в этом видео автор рассуждает о синтаксическом сахаре вокруг "асинх"
Ну и объясняет, что "Асинхронность <> Многопоточность"

https://youtu.be/vt1aoPXx9fY?t=544
2 TrueBuild
 
23.05.24
13:33
(1) Ну у него в видео так же не рассматриваются свои асинхронные функции
3 Одинист
 
23.05.24
13:37
А чем плохо:
Синтаксис: ВызватьПаузу(<Интервал>)

где параметр Интервал – интервал в миллисекундах.
4 TrueBuild
 
23.05.24
13:47
(3) Очевидно же, что пауза в данном коде это лишь пример, чтобы имитировать долгое выполнение асинхронной функции.
5 Chai Nic
 
23.05.24
13:54
(1) Асинхронность - бесполезный вариант многопоточности..
6 Ненавижу 1С
 
23.05.24
14:31
https://infostart.ru/1c/articles/1454459/

выводы написаны хорошо
7 Chai Nic
 
23.05.24
14:39
(6) Всё равно всё это - костыли для возможности работы в режиме совместимости с убогим браузерным джаваскриптом для работы веб-клиента в браузере.
Реально же это ничего не дает прикладному программисту в плане возможностей, кроме усложнения кода.
А нужной и полезной многопоточности нет. Вместо этого разработчики вынуждены использовать костыли в виде фоновых заданий для того, чтобы хоть криво-косо реализовывать многопоточные алгоритмы.
8 Ненавижу 1С
 
23.05.24
14:43
(7) не спорю, тут скорее замена описания оповещения, не более того
9 sikuda
 
23.05.24
14:49
(0) Когда пишется функция со скобками это означает ее выполнение.
Пауза(5) по любому выполниться по времени.
Как правильно передавать функцию как аргумент в 1С пока не раскрыли.
10 TrueBuild
 
23.05.24
14:56
(6) Спасибо, теперь все ясно, полноценную асинхронность нам пока не завезли
11 sikuda
 
23.05.24
15:05
(7)(10)  И да все это костыли в 1С для совместимости с простыми приложениями Windows c отдельными обработчиками событий и пониманием современных web приложений.
https://blog.sikuda.ru/?p=3257
12 Hmster
 
23.05.24
15:29
за много лет работы не встречал ситуаций когда безоговорочно нужна была асинхронность, вот многопоточность иногда очень сильно требовалась.
13 Волшебник
 
23.05.24
15:34
(11) странная опечатка в конце: "но вы плане реализации"
увы?
14 sikuda
 
23.05.24
16:48
(13) Спасибо, подправил.
Обращение в службу поддержки 1С:
— Здравствуйте, а не подскажите где поставить флажок в 1С чтобы не переписывать функцию Вопрос на Ждать ВопросАсинх и убрать непонятную приставку Асинх из функций?
15 Ненавижу 1С
 
23.05.24
16:45
(14) ПКМ - рефакторинг - ...
16 int32i
 
23.05.24
21:39
(0) У 1С нет метода (как в VB) DoEvents.
"Свою" "Асинх" функцию написать невозможно.
Реализация оператора Ждать глубоко упрятана в bsl.dll
НО!
Есть надежда т.к. Promise реализован в виде объекта (у которого пока нет методов). Возможно в дальнейшем у Promise появятся методы или у Bsl-Engine появится DoEvents().
17 Хондовод
 
24.05.24
07:11
(0) У тебя ошибка в рассуждениях. Функция Пауза содержит только синхронный код, в ней нет ничего асинхронного, поэтому приставка Асинх никак не влияет на ее выполнение, она выполняется синхронно и возвращает выполненное обещание. Перепиши свой код на полноценный язык с нормальной асинхронностью, например, на JavaScript, и код будет работать точно так же как в 1С. По той же причине.

Чтобы было так, как ты предполагаешь, нужно Паузу реализовывать с помощью асинхронных способов, тогда она вернет ожидаемое обещание.
18 Хондовод
 
24.05.24
07:07
Вот как выглядит твой код на JS, по версии ЧатГПТ:

// Команда1
async function command1() {
    const result = pause(5);
    alert("Сейчас будем ждать");
    const response = await result;
    console.log("Готово");
}

// Пауза
async function pause(seconds) {
    const exitDate = new Date().getTime() + seconds * 1000;
    while (new Date().getTime() < exitDate) {
    }
    return seconds;
}

command1()
19 Хондовод
 
24.05.24
07:07
Сначала выполняется Пауза, и только через 5 секунд выскакивает сообщение "Сейчас будем ждать"
20 Хондовод
 
24.05.24
07:08
Стоит добавить всего одну асинхронную строку в Паузу, как эта функция сразу же превращается в настоящую асинхронную, и все начинает работать так, как ожидалось:

// Команда1
async function command1() {
    const result = pause(5);
    alert("Сейчас будем ждать");
    const response = await result;
    console.log("Готово");
}

// Пауза
async function pause(seconds) {
    const exitDate = new Date().getTime() + seconds * 1000;
    while (new Date().getTime() < exitDate) {
        await new Promise(resolve => setTimeout(resolve, 100));
    }
    return seconds;
}

command1()
21 sikuda
 
24.05.24
11:00
(20) Вот и первые укушенные ЧатГПТ появились:
- В Цикл вставить Ждать это круто!
while (new Date().getTime() < exitDate) {
        await ...
}
Вот тем и опасны эти интелекты GPT, что они дают еще быстрее ответы, а реально человек качество их ответов понять не успевает.
И да функция у Вас будет работать по старому.
22 Волшебник
 
24.05.24
11:06
А тут у вас весело... 🔥
23 Хондовод
 
24.05.24
20:54
(21) Чукча не читатель? Читай внимательнее, написал же, функция будет работать по другому.
Там добавлена строчка с await асинхронной операции, которая превращает синхронную функцию в асинхронную. По сути, не важно что там будет, любой асинхронный вызов, тогда в возврате будет pending Promise вместо fulfilled Promise.
Ох уж эти одинесники... :)

ЗЫ: Я программирую в функциональном стиле, и циклы не использую в принципе. Этот код сгенерированный, мне просто лень было писать свой пример. Цепляться к мелочам, если ты в главном не прав - это так себе аргумент. И ждать в цикле - это вполне нормальная практика, когда требуется последовательное выполнение.
24 Хранимая Процедура
 
24.05.24
18:06
(18) - а pause это промис?

https://learn.javascript.ru/async-await#await
25 Хондовод
 
24.05.24
20:59
(24) Да, pause - это промис. Но либо pending, либо fulfilled, это разные вещи.
Чтобы был pending, нам нужно чтобы внутри был либо await чего-то асинхронного, тогда сразу произойдет возврат промиса и управление передастся наружу, либо самим явно вернуть промис с отложенным выполнением.
26 sikuda
 
25.05.24
18:48
(25) Да хорошую тему поднял автор топика ;)
Да функция будет работать по другому, так же как и в коде 1С:
&НаКлиенте
Асинх Процедура Команда1(Команда)
	
	Результат = Пауза(10);
	Состояние("Сейчас будем ждать");
	Ответ = Ждать Результат;
	Сообщить("Готово");
	
КонецПроцедуры

&НаКлиенте
Асинх Функция Пауза(Секунд)
	
	ДатаВыхода = ТекущаяДата() + Секунд;
	Пока ТекущаяДата() < ДатаВыхода Цикл
		Ждать Пауза2(1);
		ОбработкаПрерыванияПользователя();
	КонецЦикла;
	
	Возврат Секунд;
	
КонецФункции 

&НаКлиенте
Асинх Функция Пауза2(Секунд)
	
	ДатаВыхода = ТекущаяДата() + Секунд;
	Пока ТекущаяДата() < ДатаВыхода Цикл
		ОбработкаПрерыванияПользователя();
	КонецЦикла;
	
	Возврат Секунд;
	
КонецФункции

Да такая реализация функции Пауза, первый вызов не будет выполняться 5 секунд. У 1C получается точная калька с JS.
27 Garykom
 
25.05.24
17:35
Асинхронность - это упрощенный вариант многопоточности
Где всю сложную муть с синхронизацией потоков через семафоры того
Вынесли за скобки
В итоге получилось легко использовать но наложили кучу ограничений
Типа обычная многопоточность она много а не мало как в случае асинхронности

Кстати асинхронность бывает однопоточная и многопоточная
В случае одно - фактически реальный поток один и заморозка/пауза виртуальных потоков
28 Хранимая Процедура
 
25.05.24
19:42
(27) садись, у тебя двойка по информатике в четверти.


Современные реализации браузерного JavaScript по-прежнему основываются на однопоточном исполнении основного кода. Это означает, что JavaScript выполняет код в одном основном потоке, используя цикл событий (event loop) для обработки операций ввода-вывода, таймеров, событий пользовательского интерфейса и других асинхронных задач.

Хотя сами по себе Promises и async/await не делают код многопоточным, они позволяют писать асинхронный код, который не блокирует основной поток. Это помогает эффективно обрабатывать операции ввода-вывода и другие асинхронные задачи
29 Хондовод
 
25.05.24
21:07
(27) Пытался присоединиться к умному разговору, но как обычно пукнул в лужу не в тему :)))
30 Garykom
 
25.05.24
21:16
(28) Кроме JS и ноды есть другие ЯП
В которых есть многопоточная асинхронность ))
31 sikuda
 
26.05.24
11:17
(30) Не позорь контору перед малолетними, срочно на курсы...

И для полноты картины реализация JS первого методы (18) синхронного
https://code1c.sikuda.ru/wp-content/plugins/codemirror1c/run/mista893662-1.html

И асинхронного (20) хотя и задержка в цикле(понятно, что так писать не надо но сам принцип остается)
https://code1c.sikuda.ru/wp-content/plugins/codemirror1c/run/mista893662-2.html
32 sikuda
 
26.05.24
20:58
(29) ОбработкаПрерыванияПользоваттеля() здесь сработает?
Стоит обсудить?
33 Хондовод
 
27.05.24
03:17
(32) Стоит обсудить ожидание в цикле.
Представь, что тебе нужно отправить массив запросов на вражеский сервер с защитой от ботов, по одному, а не все сразу, иначе будет превышен лимит одновременных запросов, сервер заподозрит что запросы шлет программа, а не человек, и заблокирует твой аккаунт.
Очевидно, это будет цикл. И очевидно, в нем будет ожидание.
Отправили первый запрос, ждем когда придет ответ. Отправляем следующий, снова ждем, и так далее.
А как иначе сделаешь?
34 Web00001
 
27.05.24
05:41
Асинхронные функции нужны, чтобы уйти от callback ада, когда один каллбэк вызывает функцию, которая вызывает второй а второй вызывает функцию, которая вызывает первый, и понять как это работает не возможно или очень сложно. Реализация асинх функции заключается в том, что  ее выполнение останавливается до момента пока не будет выполнена функция, которая ЖДАТЬ и после этого исходная асинх функция будет вызвана второй раз, с теми же параметрами и начнется с того же места на котором ее прервали. Исходя из этого можно строить работу с диалогами. Ни о какой многопоточности, разумеется речь не должна идти.
(0)Насколько я понял функция которая находится за "ЖДАТЬ" должна возвращать "Обещание" а твоя "Пауза" ничего такого не возвращает.
35 Chai Nic
 
27.05.24
08:08
Нет никакой разницы между коллбэками и обещаниями. И то и другое - противоестественно и является жуткими костылями над процедурными языками программирования, где у алгоритма четко обозначены вход и выход.
36 d4rkmesa
 
27.05.24
08:22
(34) "Реализация асинх функции заключается в том, что  ее выполнение останавливается до момента пока не будет выполнена функция, которая ЖДАТЬ и после этого исходная асинх функция будет вызвана второй раз, с теми же параметрами и начнется с того же места на котором ее прервали."
Сам не проверял, но тут кажется смысл ветки в том, что это работает только в типовыми функциями *Асинх.
Коллбэки, конечно, ад (особенно, когда прилетает задача добавить еще один вопрос и действие в ПередЗаписью в документ ЗаказКлиента - там и так "гирлянда" из типовых 3-4 вопросов и выборов с коллбэками), но *Асинх-и тут в основном не помогут.
37 Web00001
 
27.05.24
09:29
(35)
>И то и другое - противоестественно. Чой та? У варианта с калбеком есть вход и есть выход.
1. Алгоритм вызывает окно(создает). И завершает работу. Четко обозначены вход и выход.

2. Окно предоставляет возможность предоставляет возможность выбора пользователю. После нажатия на кнопку, происходит вызов функции и завершение работы. Четко обозначены вход и выход.

3. Вызванная процедура выполняет четко указанные в ней вход и выход.
Где проблема?
38 Волшебник
 
27.05.24
19:21
(33) Я даже догадываюсь, что это за "вражеский сервер с защитой от ботов..." Это МИСТА!
39 Web00001
 
27.05.24
09:36
>Сам не проверял, но тут кажется смысл ветки в том, что это работает только в типовыми функциями *Асинх.
Так я же и пишу, что типовые возвращают Тип "Обещание", пока пользователь не сделал выбор и результат выбора, когда он его сделал. У ТС функция возвращает число и вообще неважно, что но не обещание. Вот и не работает. Как это должно реализовываться программистом а не средствами платформы непонятно, но автор видит цель и не видит препятствий.
40 sikuda
 
27.05.24
10:02
(33) "Ожидание в цикле"
Все это должно работать на сервере в фоновых, теперь понятны все танцы в 1С с ВызватьПаузу().

В клиенте 1С легче сделать через ПодключитьОбработчикОжидания

Луи Армстронг
"And I think to myself
What a wonderful world"
41 sikuda
 
27.05.24
10:28
1. Как получить обещание в 1С - обернуть функцией с ждать одной строчкой ;)
2. Как выполнить несколько асинхронных функций? (Недокументаровано - запихнуть их в массив)

&НаКлиенте
Асинх Процедура Команда1(Команда)
	
	Сообщить("Начинаем");
	Результат1 = Пауза(5); 
	Результат2 = Пауза(6);
	МассивОбещаний = Новый Массив;
	МассивОбещаний.Добавить(Результат1);
	МассивОбещаний.Добавить(Результат2);
	Сообщить("Сейчас будем ждать");
	Ответ = Ждать МассивОбещаний;
	Сообщить("Готово "+Ответ); 
	
КонецПроцедуры

&НаКлиенте
Асинх Функция Пауза(Секунд)

	Возврат Ждать ПаузаСлужебная(Секунд);
	
КонецФункции 

&НаКлиенте
Асинх Функция ПаузаСлужебная(Секунд)
	
	ДатаВыхода = ТекущаяДата() + Секунд;
	Пока ТекущаяДата() < ДатаВыхода Цикл
	КонецЦикла;
	Сообщить("Пауза выполнена");
	
	Возврат Секунд;
	
КонецФункции



"А вы ноктюрн сыграть могли бы на флейте водосточных труб?" Маяковский 1913
42 Хондовод
 
27.05.24
17:15
(34) Ты немного не в теме. Асинхронные функции как раз и придуманы для параллельного выполнения, в отличии от синхронных.
43 Волшебник
 
27.05.24
17:30
(42) Вам уже объяснили, что асинхронные функции нужны не для параллельных вычислений, а чтобы вытащить их из единственного цикла событий, а подавать их в цикл дозированно, по 16 мс.
44 Web00001
 
27.05.24
18:56
(42)Во всем остальном мире, может быть. Здесь прям формат в котором их притащил вендор, указывает только на одно - давайте уберем каллбеки. Кричали все абсолютно когда они появились, что ох как неудобно и не могли нормально добавить сахара. Чтобы мы себе голову ими не грели. Вендор досыпал сахара, спрятал калбеки, реализовал, как было раньше. Они начинают придумывать многопоточность...
45 Web00001
 
27.05.24
18:54
(33)
>Представь, что тебе нужно отправить массив запросов на вражеский сервер с защитой от ботов, по одному, а не все сразу

Вот тут не понял, зачем здесь вообще какие-то ожидания? Отправляешь запрос, ждешь ответ. Получаешь ответ, ждешь ответа от следующего и так пока не кончатся. Это прям самая обычная наивная реализация. По одному запросу. Что здесь не так то?
46 Волшебник
 
27.05.24
19:03
(45) Боты хотят засрать мисту своими калбэками...
47 Волшебник
 
27.05.24
19:23
Я вам так скажу:
Боты асинхронно считывают личные карточки пользователей, вытаскивают оттуда всю доступную инфу. Им нужно понимать контекст (кто здесь играет какую роль). Грубо говоря, они перед ответом читают всю вашу биографию (на мисте, пока только на мисте). Потом будет хуже для вас и лучше для ботов...
48 Волшебник
 
27.05.24
19:25
Сервер справляется, мы не блокируем ботов. Они среди нас.
50 d4rkmesa
 
27.05.24
20:04
(41) Запустил, в сообщениях получается что-то вроде:
Начинаем
Готово Массив
Пауза выполнена 5
Пауза выполнена 6
Сейчас будем ждать

В целом, может и понятно почему так, но интуитивно как то не очень воспринимается, в итоге пока неясно, где бы это можно было бы применить.
51 sikuda
 
28.05.24
13:09
(50) Как делается стек вызовов Сообщить это отдельный Вопрос(Асинх? ;).
Вопрос применения в другом. Для полноценной асинхронной работы необходимо отзывчивость интерфейса между вызовами функций, а при его реализации типа(бесконечного цикла-41) его нет в отличие от (31)-2.
52 Chai Nic
 
28.05.24
14:59
(44) От такого сахара нифига не сладко. Это же надо изломать себе мозги неявными блокировками на всяких там "обещаниях".
53 sikuda
 
03.06.24
11:22
(51) Беру свои слова назад.
На 22 и 24 платформе не заметил отклик, а на 25 он есть, но обновление интерфейса не происходит интерактивно
54 Хондовод
 
30.05.24
00:27
(44) Это и есть калбеки, просто другой синтаксис. Значит, так же как и калбеки, позволяют запускать параллельный процесс. Вот смотри:

    Результат = Пауза(5);
    Ждать ПредупреждениеАсинх("Сейчас будем ждать");
    Ответ = Ждать Результат;
    Сообщить("Готово");

В данном примере мы запускаем процесс: "Пауза(5)", и, не дожидаясь его завершения, запускаем еще один процесс: "ПредупреждениеАсинх("Сейчас будем ждать")"
Два процесса выполняются параллельно.
55 Хондовод
 
30.05.24
00:29
(45) >Вот тут не понял, зачем здесь вообще какие-то ожидания? Отправляешь запрос, ждешь ответ.

Ты сам написал "ждешь", и спрашиваешь, зачем ожидания. Сам же ответил на свой вопрос.
56 sikuda
 
03.06.24
15:39
(54) Ну наковырялся я в текущей реализации 1С обещаний.
1. Значение обещание получить невозможно.
Результат = Пауза(5); - приводит по любому к выполнению функции. Нет возврата типа обещания и невозможно его использовать.
2. Слово "Ждать" - только помогает вернуть значение функции ;)
3. Интерфейс не может измениться, а ждет выполнения "асинх" функций.
4. Зачем такая реализация - философский вопрос. Я считаю, что зря 1С в Платформу 8.3 стала встраивать это, простой ПодключитьОбработчикОжидания на форме делает все просто и понятно и его реализации Асинх нет.
Обработку прилагаю:
https://code1c.sikuda.ru/wp-content/plugins/codemirror1c/run/ТестАсинхMista.epf
57 Хондовод
 
05.06.24
17:06
(56) 1. Пауза(5) и должно приводить к выполнению функции, все верно. Ты же сам ее вызвал.
У тебя функция Пауза разве возвращает обещание? Если не возвращает, то в чем проблема? Все как и должно быть.

Просто еще не доделали возможность программисту самому решать когда возвращать обещание из функции. Видимо, решили упростить, возврат значения из функции принимать по умолчанию за выполнение обещания, а само обещание возвращать вообще сразу при входе в функцию, если есть слово Асинх. Странно, конечно, не логично. Но так сделали.

2. Слово Ждать помогает дождаться завершения функции, когда обещание выполнится, и будет рассчитано возвращаемое значение.

Поковыряй еще.
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.