powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
12 сообщений из 12, страница 1 из 1
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564581
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток.

Решил поделиться с коллегами наболевшим. Долгое время раздражала отсутствие интерактивности при работе в Cache' через вэб технологию. Что это значит:
Допустим нам надо выполнить очень большой SQL запрос, поместить результат в EXEL (xml) файл. , и по окончанию закачать его на сторону клиента, причем самое гадкое в том, что клиент очень желает видеть процесс создания этого файла. А еще веселье в том, что у клиента очень шаловливые ручки, и он любит обновлять страницу, а то и вовсе закроет браузер. При повторной загрузке он конечно же опять нажмет на кнопку старта, и все начнется снова в новом процессе. Мне кажется данная проблема знакома многим.

Стандартный вызов #server(..Test(Arg1,arg2))# тут явно не поможет.

Для решения таких задач разработал класс HTML.RunJob https://github.com/MyasnikovIA/HTML.RunJob

Опять же приветствуется конструктивная критика, что можно улучшить. Буду очень признателен.

Пример применения (есть на ginhab):
Код: html
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.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
Class User.TestRunJob Extends %CSP.Page
{

ClassMethod OnPage() As %Status
{
     ;  <script language="JavaScript" type="text/javascript" src="HTML.RunJob.cls"></script>
     ;  <script language="JavaScript" type="text/javascript" src="%25ZHTML.RunJob.cls"></script> 
      
    &html< 
      <script language="JavaScript" type="text/javascript" src="%25ZHTML.RunJob.cls"></script>
      <button onclick='runProcess()'>Запустить процесс</button>
      <button onclick='KillProcess()'>Уничтожить процесс</button>
      <br>
      <br>
      <br>Уничтожить процесс: <button onclick='alert(callJob("..KillProc2",this.innerHTML))' id='KillProc'>---</button>
      <br>
      <br>
      <div id='info'>FrmCache</div>
      <br><progress id='progress' value="0" max="100" style='width:100%'></progress>
      <br>
      <div id='FrmCache'>FrmCache</div>
      <br>
      <br>
      <div id='demo'>eee</div>
      <br>
      <script type="text/javascript" >
      
      // Синхронный запуск класс метода
      // alert(callJob("..Test2"));

      // Синхронный запуск класс метода(Полный путь к классметоду)
      alert(callJob("User.TestRunJob.Test2"));
     
      /// функция срабатывает перед вызовом класс метода
      beginFun=function(){
          
      } 
      
      /// функция обработки запроса состояния работы процесса
      ProgressFun=function(arg){
         document.getElementById("demo").innerHTML='Wor progress:'+JSON.stringify(arg);
         if (arg.js!=undefined){  eval(arg.js);    }
         if (arg.UserJob!=undefined){  document.getElementById("KillProc").innerHTML = arg.UserJob;    }
      }
     
      /// функция срабатывает по окончанию работы процесса
      CalBackFun=function(arg){
          // document.getElementById("FrmCache").innerHTML =JSON.stringify(arg);
          document.getElementById("demo").innerHTML='';
          if (''+arg=={}){     alert('Работа закончена')    }
          document.getElementById("progress").value=0;
      }
     
      
      var JobID="MYJoB_3";
      
      /// Параметры обработки запроса
      var param=[beginFun,ProgressFun,CalBackFun,JobID,1000];
      /// запуск процесса повторно после перезагрузки страницы
      refJob(param);
      
      runProcess=function(){
         var res=callJob("..Test",param);
         document.getElementById("demo").innerHTML=res;
      }
      
      KillProcess=function(){
          killJob(JobID) ;
      }
      
     </script>
    >
    w ##class(%SYS.System).InstanceGUID()
    Quit $$$OK
}

ClassMethod KillProc2(JobProc)
{
    w $zu(4,JobProc)
}

ClassMethod Test2()
{
    w $ZDT($h)
}

///Процесс который будет работать  параллельно и очень долго  
ClassMethod Test()
{
    
    ; %runjob - имя глобала , через который происходит обмен Web морды и Cache` процесса
    s count=1000
    for a=1:1:count {   
       h 1
       s @%runjob@("info")= " Счетчик внутри процесса "_a
       s val=100\count*a
       s jsCode=""
       s jsCode=jsCode_" document.getElementById(""progress"").max = "_count_"; "
       s jsCode=jsCode_" document.getElementById(""progress"").value = "_a_"; "
       s jsCode=jsCode_" document.getElementById(""FrmCache"").innerHTML ="""_$ZDT($h)_" - "_a_"  "_val_"%"" "
       ; s @%runjob@("eval")=jsCode
       s @%runjob@("js")=jsCode
       s @%runjob@("UserJob")=$JOB
    }
    w $zdt($h)
    s @%runjob@("OK")=1 ; сообщаем Web морде о том, что процесс закончен корректно
    q
}

}
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564761
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MyasnikovIA,

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

Из своих подобных изобретений могу назвать многоуровневые статусы задач. Т.е. процесс может устанавливать статус не всей задачи целиком, а только одного определенного уровня. При установке определенного уровня статуса вышестоящие не затрагиваются, а нижестоящие затираются. Показалось очень удобным, применял в своей библиотеке формирования *.ODS файлов.
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564798
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Блок А.Н.,

Из сообщения я понял, что есть способ проще и легче. Только не понял какой. Можно пример, или ссылку где можно изучить эту технологию :)
А огород написан по той причине, что не знал иного способа. Хотел бы прокачать свой уровень, за счет коллег :)
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564829
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MyasnikovIA , помимо кащейских
Код: javascript
1.
2.
3.
#server(..Test(Arg1,arg2))#
// и
#call(..Test(Arg1,arg2))#


Есть и "стандартные" методы общения клиента с сервером... Например все тот же ajax/.

Против повторных запусков используется простая блокировка "сигнальных" узлов/глобалов...

Остается организовать прогресс на сервере и отображение его на клиенте.
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564890
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MyasnikovIA,

Ну, собственно, krvsa все сказал, только я бы на #call не особо надеяться, как способ асинхронного вызова.
Не возражаете, если на псевдокоде?

Веб страница:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
<Кнопка запуска>
<Область отображения прогресса>
...
</Область отображения прогресса>
<script language=javascript>
ЗапуститьОтчет(){...}
ПроверитьСостояниеПрогресса(){...}
ПроверитьРазрешениеЗапускаСВыбраннымиПараметрами(){...}
</script>

Код: plaintext
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.
/// Класс отчета. Большинства методов можно выносить в абстрактный родительский класс
Class Report
{
/// Запустить отчет асинхронно. Вернет 1, если запущено
ClassMethhod RunAsync(params) as %Boolean
{
 ret:'..CheckStartPermission(params) 0
 job PrepareData(params)
 ret 1
}
/// Проверить разрешение старта с выбранными параметрами
Classmethod CheckStartPermission(params) as %Boolean
{
 s permisson=..Lock(params) 
 d ..Unlock(params)
 ret permission
}
ClassMethod Lock(params)
{
 lock ^report(params):0
 ret $test
}
ClassMethod Unlock(params)
{
 lock -^report(params)
}
ClassMethod PrepareData(params)
{
 s lock=..Lock(params)
 ret:'lock
 /// Установить статус процесса 

 for
 {
 ///Обновить статус процесса
 ....
 }
 d ..Unlock(params)
}
}

Все, в общем, просто, и все вы это знаете
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564911
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
krvsa,

Как раз это и реализовано в HTML.RunJob
Запускается процесс, при этом инициируется глобал с именем идентификатора "MYJoB_3" и глобальна и переменная с именем %runjob
Все значения записанные в глобал @%runjob@(“Arg1”)=”Val” в процессе опроса состояния вернутся как JSON объект {…,”Arg1”:”Val”} и будут помещены в качестве входного аргумента JS функции “ ProgressFun=function(arg){ } “ – из примера

Таким образом организован обмен информацией из запущенного процесса и браузером.

Если глобал будет уничтожен, или в нем появится ветка с именем “OK”=1 , тогда опрос состояния процесса прекратится и запустится JS функция CalBackFun=function(arg){ }

Что касается огорода, то основной код был взят из JS “/csp/broker/cspxmlhttp.js“ ответная часть на сервере cache’ тоже взята из системного класса %CSP.Broker.cls . все было переработано и объединено в одном классе(для удобства развертывания).
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564932
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MyasnikovIAКак раз это и реализовано в HTML.RunJob
Дело твое...
Просто я согласен с этим высказыванием
Блок А.Н.Что-то все-таки это слишком большой огород для такой задачи.
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564938
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В JS появляются следующие функции :
callJob – функция запуска процесса
refJob - функция восстановления процесса
killJob - функция уничтожения процесса
и если библиотека подключается в cache классе, то библиотека cspbroker.js не будет подключена, в связи с чем я переопределяю js функцию cspCallHttpServerMethod
она вызывается в тех случаях когда в JS коде встречается конструкция #call( … )#

При запуске callJob в первом параметре передается имя классметода в полном или коротком представлении ( "..Test2" или "User.TestRunJob.Test2" )

Если вторым аргументом подается массив простой аргумент (строка , число) тогда работает как обыкновенный синхронный запрос, аналогично работе #server(…)#.

Если на вход вторым аргументом подается массив объектов в виде:
var param=[beginFun,ProgressFun,CalBackFun,”JobID”,1000];
Код: html
1.
2.
3.
4.
5.
 beginFun(){}         – js функция срабатывает сразу же после запуска cache метода
ProgressFun(arg){}  – js функция срабатывает при опросе состояния процесса  
CalBackFun(arg){}   – js  функция срабатывает после окончания работы cache  класс-метода, или если процесс уничтожен
”JobID”        –  идентификатор процесса по которому производится опрос состояния
1000            –   интервал опроса состояния процесса

тогда класс метод запускается в параллельном потоке. При этом функция ProgressFun повторно вызывается через 1000 мсек. (время задается в параметре четвертым аргументом) .

Все остальные аргументы помещаются как входящие аргументы cache класс-метода
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564939
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
все это после подключения в HTML коде класса
<script language="JavaScript" type="text/javascript" src="HTML.RunJob.cls"></script>
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39564940
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
krvsa,

Спасибо за мнение. Это на самом деле важно.
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39565375
Sheonn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MyasnikovIA,
Т.е. в CSP это использовать нельзя из-за переопределения cspCallHttpServerMethod?
...
Рейтинг: 0 / 0
Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
    #39565502
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Sheonn,

Использовать можно
в классе HTML.RunJob присутствует следующая конструкция (в районе строки 592 -+ 5 строк)
Код: javascript
1.
2.
3.
     if (typeof cspCallHttpServerMethod !== 'function') {
         cspCallHttpServerMethod=callJob;
     }



Благодаря этой конструкции, если функция cspCallHttpServerMethod не определена, тогда она определяется.

Если определить в CSP внутри тэга HEAD
Код: html
1.
2.
3.
<HEAD> 
   <script language="JavaScript" type="text/javascript" src="HTML.RunJob.cls"></script>
</HEAD> 


Перед выполнением Cache добавит пере закрывающим тэгом "</HEAD>" библиотеки "cspxmlhttp.js" и "cspbroker.js"
и получится конструкция
Код: html
1.
2.
3.
<HEAD> 
<script language="JavaScript" type="text/javascript" src="HTML.RunJob.cls"></script>
<script language="JavaScript" type="text/javascript" src="/csp/broker/cspxmlhttp.js"></script><script language="JavaScript" type="text/javascript" src="/csp/broker/cspbroker.js"></script></HEAD>




В связи с этим cspCallHttpServerMetho будет сначала создан в HTML.RunJob.cls а затем переопределен в cspxmlhttp.js
и все будет работать по старому.

Код: html
1.
2.
3.
callJob – функция запуска процесса
refJob - функция восстановления процесса
killJob - функция уничтожения процесса


Никто не запрещает закомментировать HTML.RunJob условие перед инициализацией , и оставить
Код: javascript
1.
cspCallHttpServerMethod=callJob;


Но надо помнить, что подключать HTML.RunJob надо будет после закрывающего тэга </head> иначе библиотека "cspxmlhttp.js" опять переопределит её.

Это может понадобится, в тех случаях, когда есть желание использовать HTML.RunJob и есть необходимость скрыть от пользователя имя вызываемого класс метода при применении конструкции:
Код: html
1.
 #call(..Test([beginFun,ProgressFun,CalBackFun,”JobID”,1000],arg1,arg2) )#
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Интерактивный вызов класс-методов Cache из Вэббраузера (без "Таймаута")
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]