В разработке на платформе 1С:Предприятие 8.3 одной из самых фундаментальных задач является правильная организация взаимодействия между клиентом и сервером. Начинающие разработчики часто сталкиваются с трудностями, когда пытаются вызвать серверный код, передать в него данные из формы и, что не менее важно, вернуть результат обратно для выполнения логики на клиенте (например, для вывода предупреждения или открытия другой формы). В этой статье мы подробно разберем, как грамотно использовать функции для получения данных с сервера, проанализируем типичные ошибки и рассмотрим лучшие практики программирования.
Прежде чем переходить к коду, давайте разберем, почему возникают ошибки типа "Переменная не определена" или "Недостаточно фактических параметров". В управляемом приложении код четко разделен на клиентскую и серверную части. Для управления этим разделением используются директивы компиляции:
Предупреждение()).Объект.Менеджер или другим реквизитам — их нужно передавать в функцию в качестве параметров.Рассмотрим ситуацию: нам нужно проверить, существует ли в базе документ "Задание менеджера" на текущую дату для конкретного сотрудника. Поскольку запрос к базе данных возможен только на сервере, мы создадим функцию. Мы будем использовать директиву &НаСервереБезКонтекста, так как это наиболее производительный метод.
Давайте проанализируем код серверной функции:
&НаСервереБезКонтекста
Функция НайтиЗаданиеМенеджераНаТекущуюДату(Знач Менеджер)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ЗаданиеМенеджера.Ссылка КАК Ссылка
|ИЗ
| Документ.ЗаданиеМенеджера КАК ЗаданиеМенеджера
|ГДЕ
| ЗаданиеМенеджера.Проведен = ИСТИНА
| И ЗаданиеМенеджера.Менеджер = &Менеджер
| И ЗаданиеМенеджера.Дата МЕЖДУ &НачалоДня И &КонецДня";
// Используем ТекущаяДатаСеанса для корректной работы в разных часовых поясах
ТекущийМомент = ТекущаяДатаСеанса();
Запрос.УстановитьПараметр("Менеджер", Менеджер);
Запрос.УстановитьПараметр("НачалоДня", НачалоДня(ТекущийМомент));
Запрос.УстановитьПараметр("КонецДня", КонецДня(ТекущийМомент));
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
Возврат Неопределено;
Иначе
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.Ссылка;
КонецЕсли;
КонецФункции
В этом примере мы возвращаем не просто Истина или Ложь, а саму ссылку на найденный документ. Это более профессиональный подход: если документ найден, мы сразу сможем открыть его на клиенте, не делая повторных запросов.
Теперь разберем, как правильно вызвать эту функцию из обработчика события ПриИзменении на клиенте. Основная ошибка начинающих — попытка обратиться к реквизиту Менеджер напрямую внутри серверного вызова. На клиенте мы должны передавать Объект.Менеджер.
Рассмотрим по шагам логику клиентской процедуры:
&НаКлиенте
Процедура МенеджерПриИзменении(Элемент)
// 1. Проверяем, заполнено ли значение на клиенте, чтобы не гонять пустой запрос на сервер
Если ЗначениеЗаполнено(Объект.Менеджер) Тогда
// 2. Вызываем серверную функцию и ловим результат в переменную
// Передаем именно Объект.Менеджер, так как мы работаем без контекста
СсылкаНаДокумент = НайтиЗаданиеМенеджераНаТекущуюДату(Объект.Менеджер);
// 3. Анализируем полученные данные
Если ЗначениеЗаполнено(СсылкаНаДокумент) Тогда
// Если документ найден, предлагаем пользователю его открыть
ПоказатьЗначение(, СсылкаНаДокумент);
Иначе
// Если документ не найден, выводим предупреждение и ограничиваем доступ к форме
Объект.ТолькоПросмотр = Истина; // Пример блокировки формы
ТекстСообщения = "На сегодня у менеджера нет проведенного задания! Форма заблокирована.";
ПоказатьПредупреждение(, ТекстСообщения);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию, описанную в сообщениях форума, где возникала ошибка "Переменная не определена (Менеджер)". Это происходит потому, что в клиентской процедуре программист пытался написать МенеджерПриИзмененииНаСервере(Менеджер). Однако Менеджер — это реквизит объекта. На клиенте он доступен только через структуру Объект. Следовательно, правильно писать Объект.Менеджер.
Также важно помнить о количестве параметров. Если в определении функции написано Функция Имя(Параметр1, Параметр2), то при вызове вы обязаны передать оба значения, иначе система выдаст ошибку "Недостаточно фактических параметров".
Как мы увидели в примере выше, возвращая Ссылка (или Неопределено), мы получаем гораздо больше гибкости. Если ваша задача — просто проверить наличие, то Истина/Ложь достаточно. Но в 90% случаев в бизнес-логике после проверки следует действие с объектом. Если вы вернете Истина, вам придется снова идти на сервер, чтобы найти этот документ для открытия. Возврат ссылки позволяет избежать лишнего "round-trip" (похода на сервер), что критически важно для производительности системы.
Обратите внимание, что в примере кода использована функция ПоказатьПредупреждение() вместо старого метода Предупреждение(). В современных версиях платформы 1С (начиная с 8.3.15 и выше) работа в режиме "без модальности" является стандартом. Асинхронные методы не блокируют выполнение всего приложения и корректно работают в веб-клиенте. При написании нового кода всегда старайтесь использовать методы с префиксом Показать....
Для успешного получения данных на клиенте через функцию придерживайтесь следующего алгоритма:
&НаСервереБезКонтекста.Возврат, чтобы передать результат обратно.Результат = МояФункция(Параметры);.Такой подход сделает ваш код чистым, быстрым и устойчивым к ошибкам, что крайне важно для профессиональной разработки в среде 1С:Предприятие.