Тривалі операції
1. Під час розробки конфігурацій, що підтримують роботу через вебклієнт, слід уникати тривалих викликів із клієнтського коду до серверного. У клієнт-серверному режимі роботи всі тривалі серверні виклики, які можуть виконуватися понад 20 секунд* у звичайних сценаріях роботи користувача, слід виконувати асинхронно, за допомогою фонового завдання.Додаток. Допоміжні функції.
1. Під час розробки конфігурацій, що підтримують роботу через вебклієнт, слід уникати тривалих викликів із клієнтського коду до серверного. У клієнт-серверному режимі роботи всі тривалі серверні виклики, які можуть виконуватися понад 20 секунд* у звичайних сценаріях роботи користувача, слід виконувати асинхронно, за допомогою фонового завдання.
* Примітка: умовна оцінка граничної тривалості серверного виклику, допустима для поширених браузерів і вебсерверів
До таких операцій належать: формування звіту, групове оброблення об'єктів, завантаження або вивантаження даних до іншого застосунку, заповнення великих табличних частин тощо.
Інакше такі виклики можуть призвести до втрати працездатності застосунку:
- через «зависання» браузера (зазвичай браузери пропонують припинити виконання скриптів на завислій сторінці або закрити її),
- або через аварійне завершення з помилкою перевищення встановленого часу очікування вебсервера (або додаткового програмного забезпечення, установленого на вебсервері).
2.1. Загальний підхід до асинхронного виконання тривалих серверних операцій за допомогою фонового завдання:
- Код, що виконує тривале оброблення даних, розміщується в модулі менеджера об'єкта** або в загальному модулі. Результат своєї роботи він поміщає до тимчасового сховища;
**Примітка: необхідно використовувати процедуру-обгортку в загальному модулі, яка викликатиме процедуру модуля менеджера через Выполнить. Оскільки фонові завдання можуть працювати лише з процедурами та функціями загальних модулів. - Для виконання цього коду на сервері запускається фонове завдання, при цьому необхідно очікувати завершення виконання фонового завдання протягом 2 сек (а в режимі повільного з'єднання – 4 сек);
- Якщо за час очікування виконання завдання воно не завершилося, то керування повертається на клієнт, і в клієнтському коді підключається обробник очікування, у якому періодично перевіряється стан фонового завдання. При цьому інтервал опитування завдання збільшується від 1 до 15 с із фіксованим коефіцієнтом 1.4;
- На час виконання тривалої операції користувачеві відображається індикатор;
при цьому для звітів індикатор виводиться в поле табличного документа, використовуючи властивість поля табличного документа ОтображениеСостояния:
а для інших місць – виводиться блокувальна форма (РежимОткрытияОкна = БлокироватьОкноВладельца), на якій розміщено декорацію з анімованим зображенням і кнопку «Скасувати»:![- Бухгалтери. и] UiJ Л М М+ М- X Операция выполняется... Отмена](/img/materialy_dlitelnye_operatsii/demo2.png)
- Після отримання від сервера інформації про те, що фонове завдання завершено, отриманий результат завантажується з тимчасового сховища та обробляється.
2.2. Асинхронне формування звіту потрібне лише для тих звітів, які
- розроблено без використання СКД або з використанням СКД, але з перевизначеною процедурою формування звіту (перевизначено обробник кнопки «Сформувати» або в обробнику модуля звіту ПриКомпоновкеРезультата установлюється СтандартнаяОбработка = Ложь).
- і формування яких, як правило, займає тривалий час.
Поведінка таких звітів має бути максимально схожою на поведінку звітів на базі СКД, а саме:
- форму звіту не слід блокувати на час його формування;
- користувач може змінити налаштування та переформувати звіт, не чекаючи завершення його формування;
- під час закриття форми звіту формування звіту переривається.
3. Приклад заповнення табличної частини Реалізація документа ФормуванняЗаписівКнигиПродажів.
У модулі менеджера розміщується процедура підготовки даних для заповнення табличної частини:
Процедура ПодготовитьДанныеДляЗаполнения(ПараметрыДокумента, АдресХранилища) Экспорт ДанныеДляЗаполнения = Новый Структура; ДанныеДляЗаполнения.Вставить("Реализация", ПодготовитьДанныеРазделаРеализация(ПараметрыДокумента)); ПоместитьВоВременноеХранилище(ДанныеДляЗаполнения, АдресХранилища); КонецПроцедуры
У модулі форми документа розміщується обробник команди заповнення документа:
&НаКлиенте Процедура ЗаполнитьДокумент(Команда) ЗаданиеВыполнено = ЗаполнитьДокументНаСервере(); Если ЗаданиеВыполнено Тогда Возврат; КонецЕсли; // Операцію ще не завершено, виконується за допомогою фонового завдання (асинхронно). ПараметрыОбработчикаОжидания = Новый Структура( "МинимальныйИнтервал, |МаксимальныйИнтервал, |ТекущийИнтервал, |КоэффициентУвеличенияИнтервала", 1, 15, 1, 1.4); ПодключитьОбработчикОжидания("Подключаемый_ПроверитьВыполнениеЗадания", 1, Истина); ФормаДлительнойОперации = ОткрытьФорму("ОбщаяФорма.ДлительнаяОперация", Новый Структура("ИдентификаторЗадания", ИдентификаторЗадания), ЭтаФорма); КонецПроцедуры
який передає керування серверній функції ЗаполнитьДокументНаСервере, ініціалізує клієнтську змінну модуля форми ПараметрыОбработчикаОжидания, підключає обробник очікування Подключаемый_ПроверитьВыполнениеЗадания і відкриває форму-індикатор виконання тривалої операції ОбщаяФорма.ДлительнаяОперация.
Серверна функція ЗаполнитьДокументНаСервере у модулі форми виконує безпосередньо підготовку даних у файловому режимі роботи, а в клієнт-серверному режимі запускає підготовку у фоновому завданні, до якого передає такі параметри:
- Дані документа, необхідні для заповнення (роботи алгоритму);
- АдресХранилища – адреса тимчасового сховища, до якого фонове завдання має помістити результат виконання операції.
&НаСервере Функция ЗаполнитьДокументНаСервере() ПараметрыДокумента = Новый Структура("Дата,Организация,Реализация0", Объект.Дата, Объект.Организация, Объект.Реализация0); АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор); ЗаданиеВыполнено = Ложь; // У файловому режимі роботи виконуємо операцію безпосередньо (синхронно). Если ИнформационнаяБазаФайловая() Тогда Документы.ФормированиеЗаписейКнигиПродаж.ПодготовитьДанныеДляЗаполнения(ПараметрыДокумента, АдресХранилища); Возврат Истина; КонецЕсли; // У клієнт-серверному режимі роботи виконуємо операцію у фоновому завданні (асинхронно). НаименованиеЗадания = НСтр("ru = 'Заполнение документа ""Формирование записей книги продаж""'"); ПараметрыЗаполнения = Новый Массив; ПараметрыЗаполнения.Добавить(ПараметрыДокумента); ПараметрыЗаполнения.Добавить(АдресХранилища); Если ПолучитьСкоростьКлиентскогоСоединения() = СкоростьКлиентскогоСоединения.Низкая Тогда ВремяОжидания = 4; Иначе ВремяОжидания = 2; КонецЕсли; Задание = ФоновыеЗадания.Выполнить( "Документы.ФормированиеЗаписейКнигиПродаж.ПодготовитьДанныеДляЗаполнения", ПараметрыЗаполнения, , НаименованиеЗадания); Попытка Задание.ОжидатьЗавершения(ВремяОжидания); Исключение // Спеціальне оброблення не потрібне. Імовірно, виняток викликано закінченням часу очікування. КонецПопытки; ИдентификаторЗадания = Задание.УникальныйИдентификатор; // Якщо операція вже завершилася, то відразу обробляємо результат. Если ЗаданиеВыполнено(Задание.УникальныйИдентификатор) Тогда ЗаданиеВыполнено = Истина; ЗагрузитьПодготовленныеДанные(); КонецЕсли; Возврат ЗаданиеВыполнено; КонецФункции
Обробник очікування в модулі форми перевіряє, чи завершено фонове завдання, і завантажує результат із тимчасового сховища за допомогою виклику процедури ЗагрузитьПодготовленныеДанные:
&НаКлиенте Процедура Подключаемый_ПроверитьВыполнениеЗадания() Попытка Если ЗаданиеВыполнено() Тогда ЗагрузитьПодготовленныеДанные(); ЗакрытьФормуДлительнойОперации(); Возврат; КонецЕсли; Исключение ЗакрытьФормуДлительнойОперации(); ВызватьИсключение; КонецПопытки; ПараметрыОбработчикаОжидания.ТекущийИнтервал = ПараметрыОбработчикаОжидания.ТекущийИнтервал * ПараметрыОбработчикаОжидания.КоэффициентУвеличенияИнтервала; Если ПараметрыОбработчикаОжидания.ТекущийИнтервал > ПараметрыОбработчикаОжидания.МаксимальныйИнтервал Тогда ПараметрыОбработчикаОжидания.ТекущийИнтервал = ПараметрыОбработчикаОжидания.МаксимальныйИнтервал; КонецЕсли; ПодключитьОбработчикОжидания( "Подключаемый_ПроверитьВыполнениеЗадания", ПараметрыОбработчикаОжидания.ТекущийИнтервал, Истина); КонецПроцедуры &НаСервере Процедура ЗагрузитьПодготовленныеДанные() Результат = ПолучитьИзВременногоХранилища(АдресХранилища); Если ТипЗнч(СтруктураДанных) <> Тип("Структура") Тогда Возврат; КонецЕсли; Если СтруктураДанных.Свойство("Реализация") Тогда Объект.Реализация.Загрузить(СтруктураДанных.Реализация); КонецЕсли; КонецПроцедуры
У додатку нижче наведено приклад реалізації допоміжних функцій ЗакрытьФормуДлительнойОперации, ИнформационнаяБазаФайловая і ЗаданиеВыполнено. 4. У разі використання в конфігурації Бібліотеки стандартних підсистем у розпорядженні розробника є допоміжні функції та процедури загальних модулів ДлительныеОперации, ДлительныеОперацииКлиент, а також процедура УстановитьСостояниеПоляТабличногоДокумента загального модуля ОбщегоНазначенияКлиентСервер. Додаток. Допоміжні функції.
&НаКлиенте Процедура ЗакрытьФормуДлительнойОперации() Если ТипЗнч(ФормаДлительнойОперации) = Тип("УправляемаяФорма") Тогда Если ФормаДлительнойОперации.Открыта() Тогда ФормаДлительнойОперации.Закрыть(); КонецЕсли; КонецЕсли; КонецПроцедуры &НаСервереБезКонтекста Функция ИнформационнаяБазаФайловая(СтрокаСоединенияИнформационнойБазы = "") Экспорт Если ПустаяСтрока(СтрокаСоединенияИнформационнойБазы) Тогда СтрокаСоединенияИнформационнойБазы = СтрокаСоединенияИнформационнойБазы(); КонецЕсли; Возврат Найти(Врег(СтрокаСоединенияИнформационнойБазы), "FILE=") = 1; КонецФункции