Разработка и Конфигурация · 14 мин
Как прервать выполнение функции в 1С
Как прервать выполнение функции в 1С: оператор Возврат, Прервать для циклов, ВызватьИсключение. Примеры кода, типичные ошибки и способы проверки результата.
Во встроенном языке 1С прервать выполнение функции можно несколькими способами: оператором Возврат, который завершает процедуру или функцию и передаёт управление вызывающему коду, оператором Прервать для выхода из цикла и механизмом исключений через ВызватьИсключение. Выбор зависит от задачи: нужно ли просто досрочно выйти, вернуть значение или сообщить об ошибке выше по стеку вызовов.
Чаще всего досрочный выход нужен при проверке входных параметров: если обязательный параметр не заполнен, нет смысла выполнять дальнейшую логику. Реже требуется прервать вложенную обработку — например, остановить перебор строк таблицы при нахождении нужного элемента или аварийно завершить длительную операцию по запросу пользователя.
Важно понимать разницу между штатным завершением и аварийным. Штатный выход через Возврат не считается ошибкой: транзакция не откатывается, вызывающий код продолжает работу. Исключение, напротив, сигнализирует о нештатной ситуации и при отсутствии обработчика приведёт к откату транзакции и сообщению пользователю. Ниже разобраны все варианты с примерами и типичными ошибками.
Оператор Возврат: досрочный выход из функции и процедуры
Оператор Возврат немедленно прекращает выполнение текущей процедуры или функции и передаёт управление в точку вызова. В функции после оператора можно указать возвращаемое значение; если его не указать, функция вернёт Неопределено. В процедуре возвращаемое значение указывать нельзя — попытка сделать это приведёт к ошибке компиляции модуля.
Типовой сценарий — защитные проверки в начале функции. Вместо глубокой вложенности условий пишут последовательные проверки с выходом:
Функция ПолучитьЦенуНоменклатуры(Номенклатура, ДатаЦены) Экспорт
Если Не ЗначениеЗаполнено(Номенклатура) Тогда
Возврат 0;
КонецЕсли;
Если Не ЗначениеЗаполнено(ДатаЦены) Тогда
ДатаЦены = ТекущаяДатаСеанса();
КонецЕсли;
// основная логика получения цены
Возврат Цена;
КонецФункции
Такой стиль называют «ранним выходом»: каждая проверка сразу завершает функцию, а основной код остаётся без лишних уровней вложенности. Это упрощает чтение и снижает риск пропустить ветку условия.
Учтите: код, расположенный после оператора Возврат в том же линейном участке, никогда не выполнится. Конфигуратор при проверке модуля может выдать предупреждение о недостижимом коде — не игнорируйте его, обычно это признак логической ошибки или лишнего фрагмента после рефакторинга.
Прервать и Продолжить: управление циклами
Оператор Прервать завершает выполнение ближайшего цикла (Для, Для Каждого, Пока) и передаёт управление на первую строку после цикла. Он не выходит из функции — после цикла код продолжит выполняться. Это частая путаница у начинающих разработчиков.
НайденнаяСтрока = Неопределено;
Для Каждого СтрокаТаблицы Из ТаблицаДокумента Цикл
Если СтрокаТаблицы.Номенклатура = ИскомаяНоменклатура Тогда
НайденнаяСтрока = СтрокаТаблицы;
Прервать;
КонецЕсли;
КонецЦикла;
Если НайденнаяСтрока = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Оператор Продолжить пропускает оставшуюся часть текущей итерации и переходит к следующей. Он удобен, когда часть элементов коллекции нужно отфильтровать без вложенных условий:
Для Каждого СтрокаТаблицы Из ТаблицаДокумента Цикл
Если СтрокаТаблицы.Отменено Тогда
Продолжить;
КонецЕсли;
// обработка только активных строк
КонецЦикла;
Оба оператора действуют только на ближайший охватывающий цикл. Прервать сразу два вложенных цикла одним оператором нельзя — используйте флаг-признак или выносите внутренний цикл в отдельную функцию, из которой можно выйти через Возврат.
// Выход из двух вложенных циклов через флаг
НужноПрервать = Ложь;
Для Каждого Группа Из Группы Цикл
Для Каждого Элемент Из Группа.Элементы Цикл
Если Элемент.Код = ИскомыйКод Тогда
НужноПрервать = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если НужноПрервать Тогда
Прервать;
КонецЕсли;
КонецЦикла;ВызватьИсключение: аварийное прерывание с передачей ошибки
Когда функция не может выполнить свою задачу и вызывающий код должен узнать об этом, используйте механизм исключений. Оператор ВызватьИсключение прерывает выполнение не только текущей функции, но и всей цепочки вызовов вверх по стеку — до ближайшего блока Попытка ... Исключение ... КонецПопытки.
Функция РассчитатьСкидку(СуммаДокумента) Экспорт
Если СуммаДокумента < 0 Тогда
ВызватьИсключение "Сумма документа не может быть отрицательной";
КонецЕсли;
// расчёт скидки
КонецФункции
Вызывающая сторона перехватывает исключение и решает, как реагировать:
Попытка
Скидка = РассчитатьСкидку(СуммаДокумента);
Исключение
ИнформацияОбОшибке = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("РасчетСкидки",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
ВызватьИсключение КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
КонецПопытки;
Ключевое отличие от Возврат: если исключение не перехвачено нигде до уровня платформы, текущая транзакция откатывается, а пользователь получает сообщение об ошибке. Это правильное поведение при нарушении целостности данных, но недопустимое для штатных ситуаций вроде «пользователь не заполнил поле» — там корректнее вернуть признак ошибки или показать сообщение через объект СообщениеПользователю.
Сравнение способов прерывания
Три механизма решают разные задачи, и подмена одного другим — источник трудноуловимых ошибок. Сопоставление поможет выбрать правильный инструмент.
| Оператор | Что прерывает | Возврат значения | Откат транзакции | Когда применять |
|---|---|---|---|---|
Возврат | Текущую функцию/процедуру | Да (в функции) | Нет | Штатный досрочный выход, защитные проверки |
Прервать | Ближайший цикл | Нет | Нет | Досрочное завершение перебора коллекции |
Продолжить | Текущую итерацию цикла | Нет | Нет | Пропуск отдельных элементов коллекции |
ВызватьИсключение | Всю цепочку вызовов до обработчика | Нет | Да, если не перехвачено | Ошибки, нарушение контракта функции |
Практическое правило: если ситуация ожидаема и вызывающий код может продолжить работу — возвращайте признак результата через Возврат (например, Неопределено или структуру с флагом успеха). Если ситуация означает, что операцию продолжать нельзя и данные могут остаться в несогласованном состоянии — вызывайте исключение.
Как выбрать действие
Как прервать длительную операцию по требованию пользователя
Отдельный сценарий — длительная обработка (загрузка данных, групповое проведение документов), которую пользователь хочет остановить кнопкой. Встроенного механизма «убить функцию извне» в клиентском коде нет: прерывание организуется кооперативно, через периодическую проверку признака отмены.
Типовая схема: в форме обработки заводится реквизит-флаг «Отмена», кнопка устанавливает его в Истина, а внутри цикла обработки на каждой итерации (или каждые N итераций) флаг проверяется:
Для Каждого СтрокаДанных Из ДанныеКОбработке Цикл
Если Отмена Тогда
ВызватьИсключение "Операция отменена пользователем";
КонецЕсли;
// обработка строки
ОбработатьПрерываниеПользователя();
КонецЦикла;
В толстом клиенте и в управляемых формах при модальном выполнении используется ОбработкаПрерыванияПользователя() — метод, который позволяет пользователю прервать операцию нажатием Ctrl+Break и заодно даёт системе обработать накопившиеся события интерфейса. В клиент-серверном варианте длительные операции корректнее выносить в фоновые задания: там прерывание реализуется через ФоновоеЗадание.Отменить() либо через общий признак отмены в базе, который серверная процедура проверяет в цикле.
Учтите ограничение: если длительная операция выполняется в одной транзакции, прерывание через исключение откатит все уже сделанные изменения. Если нужна возможность остановиться «на полпути» с сохранением обработанной части — фиксируйте транзакцию порциями и храните позицию, с которой можно продолжить.
- 1Добавьте в форму или объект признак отмены (реквизит, параметр сеанса или запись в базе)
- 2Добавьте кнопку «Отменить», которая устанавливает признак
- 3В цикле обработки периодически проверяйте признак и выходите через Возврат или ВызватьИсключение
- 4При работе в транзакции решите заранее: откатить все изменения или зафиксировать обработанную часть
- 5Проверьте на тестовой копии, что прерывание не оставляет данных в несогласованном состоянии
Типичные ошибки при прерывании функций
Первая группа ошибок связана с ожиданиями от операторов. Прервать вне цикла вызывает ошибку компиляции, а внутри цикла прерывает только его, а не функцию — после цикла код продолжит выполняться, и если логика предполагала полный выход, результат будет неверным. Аналогично Возврат внутри цикла завершает всю функцию, а не только перебор, что тоже бывает неожиданностью.
Вторая группа — неочевидные последствия исключений. Частая ошибка — перехват исключения «в никуда»: пустой блок Исключение ... КонецПопытки скрывает реальные ошибки и затрудняет диагностику. Минимально корректная обработка — запись в журнал регистрации и повторный вызов исключения или осмысленная реакция.
Третья группа — использование Возврат Неопределено как сигнала об ошибке без документирования этого соглашения. Вызывающий код, написанный другим разработчиком, может не проверять результат и передать Неопределено дальше, что приведёт к ошибке в неожиданном месте. Если функция может завершиться неуспехом, делайте контракт явным: возвращайте структуру с признаком успеха или вызывайте исключение.
Как проверить, что прерывание работает правильно
После внедрения досрочного выхода проверьте три вещи. Во-первых, пройдите сценарий в отладчике по шагам (F11): убедитесь, что Возврат срабатывает на ожидаемом условии и управление попадает в нужную точку вызывающего кода. Во-вторых, проверьте возвращаемое значение в каждой ветке выхода — частая ошибка, когда в одной ветке возвращается значение нужного типа, а в другой забыто, и функция возвращает Неопределено.
В-третьих, для исключений проверьте поведение транзакции: выполните операцию, вызовите исключение на середине и убедитесь, что данные либо полностью откатились, либо зафиксированы ровно в том объёме, который предполагала логика. Несогласованные остатки или «полупроведённые» документы — признак того, что точки прерывания и границы транзакции расставлены неверно.
Как проверить результат
Возврат срабатывает на нужном условии, вызывающий код получает ожидаемое значение
Выполнение продолжается после Возврат или возвращается значение другого типа
Ошибка перехвачена, записана в журнал регистрации, пользователь получил понятное сообщение
Исключение проглатывается без следа или пользователь видит технический текст платформы
Данные целостны: либо полный откат, либо зафиксирована осмысленная часть
Часть связанных объектов изменена, часть нет — данные в несогласованном состоянии
Частые вопросы
Чем отличается Возврат в процедуре от Возврата в функции?
В процедуре оператор Возврат просто завершает её выполнение, возвращаемое значение указывать нельзя. В функции после Возврат можно указать значение, которое получит вызывающий код; если его не указать, функция вернёт Неопределено. Синтаксис Возврат с выражением внутри процедуры вызовет ошибку при проверке модуля.
Можно ли одним Прервать выйти из двух вложенных циклов?
Нет, Прервать завершает только ближайший охватывающий цикл. Для выхода из нескольких уровней вложенности используют флаг-признак, который проверяется во внешнем цикле, либо выносят внутренний перебор в отдельную функцию и выходят из неё через Возврат.
Что произойдёт, если не перехватить исключение?
Исключение поднимется по стеку вызовов до уровня платформы. Если оно произошло внутри транзакции, транзакция будет отменена со всеми внесёнными изменениями. Пользователь получит сообщение об ошибке, а в фоновых заданиях задание завершится с состоянием «Ошибка».
Как прервать уже запущенное фоновое задание?
Через метод Отменить() объекта ФоновоеЗадание, полученного по уникальному идентификатору. Это принудительная аварийная остановка, поэтому в коде фонового задания важно не держать открытую транзакцию дольше необходимого. Более мягкий вариант — периодическая проверка в цикле задания признака отмены, записанного в базу.
Что лучше для ошибки валидации: Возврат или исключение?
Если некорректные данные — ожидаемая ситуация (например, пользователь не заполнил поле), лучше вернуть признак неуспеха и показать сообщение через СообщениеПользователю. Исключение оправдано, когда нарушен контракт функции и продолжение работы приведёт к несогласованным данным. Критерий прост: штатная ситуация — Возврат, нештатная — исключение.
Работает ли ОбработкаПрерыванияПользователя на сервере?
Нет, этот метод предназначен для клиентского выполнения и позволяет пользователю прервать операцию сочетанием Ctrl+Break. В серверном коде и фоновых заданиях он не применяется — там прерывание организуется через Отменить() для фонового задания или через кооперативную проверку признака отмены в цикле обработки.
Что важно запомнить
Возврат завершает текущую функцию или процедуру штатно, Прервать и Продолжить управляют только циклами, а ВызватьИсключение аварийно прерывает всю цепочку вызовов с откатом транзакции. Выбирайте механизм по характеру ситуации, всегда обрабатывайте исключения с записью в журнал регистрации и проверяйте целостность данных после прерывания на тестовой копии.