При выполнении кода в управляемой форме на клиенте разработчики часто сталкиваются с исключением вида: Ошибка при вызове метода контекста (Прочитать): Использование синхронных методов на клиенте запрещено!. Разберем по шагам, почему возникает эта проблема и какими способами ее можно устранить.
Проанализируем ситуацию. Начиная с определенных версий платформы «1С:Предприятие 8.3», был введен курс на отказ от модальных окон и синхронных вызовов на стороне клиента. Основная цель этого изменения — обеспечение стабильной работы приложения в веб-клиенте и мобильном клиенте, где веб-браузер или мобильная операционная система блокируют синхронный доступ к локальным файлам и ресурсам компьютера.
Ошибка появляется при вызове методов вроде Прочитать() у объекта ТекстовыйДокумент или ЧтениеТекста в следующих случаях:
Рассмотрим самый быстрый способ решения, если разработка ведется в локальном тонком или толстом клиенте и приложение не планируется публиковать в веб-браузере.
Разберем порядок действий в Конфигураторе:
Важно: Данное решение подходит для локальных баз и доработок, однако при запуске в веб-клиенте браузер всё равно может заблокировать синхронную операцию.
Проанализируем наиболее современный и рекомендуемый способ разработки. В платформе 8.3.18 появились ключевые слова Асинх и Ждать, которые позволяют писать неблокирующий код в привычном последовательном стиле.
Посмотрим на пример использования метода ПрочитатьАсинх():
&НаКлиенте
Асинх Процедура ПрочитатьФайлНаКлиенте()
Текст = Новый ТекстовыйДокумент;
Ждать Текст.ПрочитатьАсинх(ИмяФайла, КодировкаТекста.UTF8);
// Последующая обработка прочитанного текста
КоличествоСтрок = Текст.КоличествоСтрок();
КонецПроцедуры
Обратим внимание на ключевые правила при работе с асинхронными процедурами:
Асинх.ПрочитатьАсинх()) обязательно указывается оператор Ждать.Рассмотрим безопасный архитектурный подход, при котором работа с содержимым файла выполняется на стороне сервера. Так как ограничения платформы на синхронные вызовы действуют только на клиенте, серверный контекст позволяет использовать стандартный метод Прочитать() без ошибок.
Разберем схему работы:
Посмотрим на пример реализации:
&НаКлиенте
Асинх Процедура ЗагрузитьФайлЧерезСервер()
// Помещаем файл во временное хранилище асинхронно
Результат = Ждать ПоместитьФайлНаСерверАсинх(ИмяФайла);
Если Результат <> Неопределено Тогда
ПрочитатьФайлНаСервере(Результат.Адрес);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПрочитатьФайлНаСервере(АдресХранилища)
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
ДвоичныеДанные.Записать(ИмяВременногоФайла);
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ИмяВременногоФайла, КодировкаТекста.UTF8);
// Обработка данных на сервере
УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры
Если используется версия платформы ниже 8.3.18, но в конфигурации запрещены синхронные вызовы, разберем вариант с использованием механизма обратного вызова.
Для этого применяется неблокирующий метод НачатьЧтение() и объект ОписаниеОповещения:
&НаКлиенте
Процедура ПрочитатьФайлЧерезОповещение()
Текст = Новый ТекстовыйДокумент;
Оповещение = Новый ОписаниеОповещения("ПослеЧтенияФайла", ЭтотОбъект, Текст);
Текст.НачатьЧтение(Оповещение, ИмяФайла, КодировкаТекста.UTF8);
КонецПроцедуры
&НаКлиенте
Процедура ПослеЧтенияФайла(Результат, ДополнительныеПараметры) Экспорт
Текст = ДополнительныеПараметры;
// Продолжение работы с объектом ТекстовыйДокумент
КонецПроцедуры
Таким образом, для исправления ошибки можно либо разрешить синхронные вызовы в настройках метаданных (для локальной разработки), либо переписать код с использованием Асинх / Ждать или переносом бизнес-логики на сервер.