В общем, у вас еще есть время соскочить. Тем же, кто «на корабле» не говорю «пристегнитесь» - не поможет…
Когда только начинаешь осваивать web-программирование, то серьезные неудобства нам, привыкшим к Word, может доставить невозможность явно задать точные координаты объектов на web-странице средствами html. Позднее, когда пытаешь реализовать на своей страничке некую интерактивность, сталкиваешься с неприятной особенностью web: при обновлении твой клиент теряет все промежуточные данные. Поэтому, организовать игру крестики-нолики, чат или корзину покупок на сайте, не прибегая к кукисам или сессиям – задача не такая и простая. Большинство же чатов, форумов, тех же корзин покупок в Интернет-магазинах чаще всего сделано достаточно топорно: ваше состояние идентифицируется записью в базе данных на сервере по некоему идентификатору. Когда вы делаете очередной запрос к серверу, то передаете ему этот идентификатор и суть запроса. Сервер находит Вашу запись, смотрит, что можно сделать и генерирует в ответ страничку, вновь возвращая идентификатор и «забывая» о вашем существовании в тот же миг. Это вполне стандартная процедура web-серфинга. Ее отличают две особенности:
1. Между моментами отправки запроса и получением ответа от сервера ваш браузер «висит»
2. При получении ответа страница полностью перерисовывается, теряя всю прежнюю информацию, например, информацию о выбранном товаре
Но сегодня мы направим наш челнок в мир асинхронной интерактивности, туда, где и первая, и вторая проблемы web решены. Более того, мы откажемся от «многотомных инструкций», связанных с PHP и MySql, заменив их привычной и всеми любимой оболочкой 1С. В завершении полета нам предстоит наблюдать рождение сверхновой, имя которой ярко и незабываемо: Асинхронный 1С-сервер: «АС-1С»
Асинхронная вселенная.
Итак, у нас есть подвисающая и перерисовывающаяся web-страничка. Давайте разделим ее на два фрейма. В первом будем делать обычные http-запросы к серверу. Разумеется, этот фрейм подвиснет, дожидаясь ответа и полностью обновится при его получении. Сделаем его невидимым. И пока наш невидимый друг «разговаривает» с сервером, мы будем продолжать работать во втором, рабочем фрейме, периодически опрашивая по таймеру состояние первого. Как только сервер подаст «условный знак», что страница в первом фрейме полностью сформировалась (например, сформирует < div id=”END”>END</div> в конце), мы без труда достанем оттуда все, что нам нужно по frame1.name.outerHTML, и лишь частично обновим содержание рабочего фрейма, не перерисовывая всей страницы в нем, а потому не теряя ни единого бита пользовательских данных.
Собственно, это и есть асинхронный подход. Он выражается в том, что два процесса (наши фреймы) работают параллельно друг с другом, обмениваясь информацией по условному сигналу.
Асинхронные запросы сплошь и рядом используются в микропроцессорной технике, когда нельзя, чтобы процесс, ожидающий ответа, «висел». Для этого назначаются "флаги" – условные биты в регистрах состояния. Если флаг поменялся с 0 на 1, то это говорит процессу, контролирующему состояние флага, что пора что-то прочитать. Сделав это, он обязательно сбрасывает флаг – просигналит о том, что данные прочитаны полностью, и он готов принять новую порцию информации. Как видите, никакой передачи управления и потери контроля.
ФОФЧ тьфу… AJAX
Приходя к радостному пониманию преимущества асинхронных запросов, незадачливый web-навигатор устремляется в поиски приемлемой технологии, реализующей такие запросы, и наталкивается на скалу под названием AJAX. С легкой руки Гарретта (не он ли был прообразом персонажа в Thief?  ) асинхронность почти повсеместно ассоциируется с php, mysql, xml javascript и страшным XMLHttpRequest … В общем, многие «ниасиливают» и отказываются от идеи асинхронности. Мы же с вами потому и в космосе, что там, где что-то «ниасиливаем», начинаем творить сами.
Асинхронный клиент
Те, кто въехал в специфику асинхронного подхода без труда напишут клиент, делающий асинхронные запросы, на любом доступном языке программирования. 1С не будет здесь исключением. Асинхронный клиент, написанный на 1С, это достаточно интересная тема. Во-первых, любое количество подключений к базе на сервере, даже если там стоит однопользовательская версия 1С. Во-вторых, никакого зависания, если сервер не отвечает. В-третьих, возможность работать из любой части галактики, где есть доступ к Интернет. Зачем и кому, спросит кто-то, могут понадобиться «асинхронные одинэсины»? Думаю, применение этой технологии может быть самым широким и неожиданным: удаленные офисы, торговые представители с ноутбуками, корпоративные справочные системы… Я использую асинхронный обмен данными при сетевом варианте работы сервера дисконтных карт в составе «Кассирочки». Кстати, всем известный «Штрих-кассир» использует именно такую технологию, передавая данные о продажах и делая запрос об остатках товаров в реальном времени в «Штрих-мастер» на сервере.
Для создания асинхронного клиента на базе 1С, воспользуемся функцией «ОбработкаОжидания». Глобальный модуль простейшего асинхронного клиента, позволяющего делать до 10-и запросов к серверу и ожидать ответа, не прекращая работу, будет выглядеть примерно так:
Перем ЕстьВопрос Экспорт; Перем ЕстьОтвет Экспорт; Перем ТекстВопроса Экспорт; Перем ТекстОтвета Экспорт; Перем ПапкаОбмена Экспорт; Функция ЗаписатьВопрос(Инфо) Экспорт Если ЕстьВопрос=1 Тогда Возврат 0; // не обработан предыдущий вопрос КонецЕсли; ТекстВопроса=Инфо; ЕстьВопрос=1; Возврат 1; // текущий вопрос записан в переменную ТекстВопроса // и ожидает отправки на сервер КонецФункции Функция БылДанОтвет() Экспорт Возврат ЕстьОтвет; // Имеется необработанный ответ в переменной ТекстОтвета КонецФункции Функция ПолучитьОтвет() Экспорт Если ЕстьОтвет=1 Тогда ЕстьОтвет=0; // Текущий ответ был прочитан, можно получать новый ответ Возврат ТекстОтвета; КонецЕсли; Возврат ""; КонецФункции Процедура РаботаССервером() Если ЕстьОтвет=0 Тогда // Если нет необработанного ответа Если ФС.СуществуетФайл(ПапкаОбмена+"ответ.txt")=1 Тогда Т=СоздатьОбъект("Текст"); Т.Открыть(ПапкаОбмена+"ответ.txt"); ТекстОтвета=Т.ПрочитатьСтроку(1); ФС.УдалитьФайл(ПапкаОбмена+"ответ.txt"); // Сообщаем серверу, что ответ прочитан ЕстьОтвет=1; // Прочитан новый ответ КонецЕсли; КонецЕсли; Если ЕстьВопрос=1 Тогда // Если есть необработанный вопрос К=1; // Проверяем, есть ли возможность записать вопрос Пока ФС.СуществуетФайл(ПапкаОбмена+"вопрос"+К+".txt")=1 Цикл К=К+1; Если К>10 Тогда Возврат; // Имеется 10 непрочитанных сервером вопросов КонецЕсли; КонецЦикла; Т=СоздатьОбъект("Текст"); Т.ДобавитьСтроку(ТекстВопроса); Т.Записать(ПапкаОбмена+"вопрос"+К+".txt"); ЕстьВопрос=0; // Текущий вопрос обработан и направлен серверу КонецЕсли; КонецПроцедуры ЕстьВопрос=0; ЕстьОтвет=0; ОбработкаОжидания("РаботаССервером ",1);
Для создания более крутого Интернет аналога, нам потребуется внешняя компонента, реализующая доступ к Интернет, и обрабатывающая наши запросы в фоновом режиме. Как только сервер присылает ответ, наша компонента должна формировать событие в процедуре ОбработкаВнешнегоСобытия.
Но можно быть проще, воспользовавшись внешним приложением, например, подключиться к браузеру по OLE и периодически опрашивать его объектную модель на наличие пресловутого < div id=”END”>END</div> . Еще проще? Пожалуйста. Запускаем параллельно еще одну 1С, и пусть она занимается Интернет с помощью стандартных библиотек, формируя текстовые файлы с полученной информацией в определенном каталоге. Мы же продолжаем работать в нашей базе. И как только мы видим появление такого файла, значит, нам прислали долгожданный ответ. Разумеется, ни что не мешает использовать прямое ftp-подключение к серверу, чтобы периодически опрашивать, а не появился ли нужный нам файлик…
Асинхронный сервер
Ну почему??? Почему какой-то там Гарретт может позволить себе брякнуть с будуна AJAX, и вся планета будет это повторять? Нет, мы-то чем хуже! Сегодня мы говорим «АС-1С» И пусть эта аббревиатура станет крылатой!
Работа нашего асинхронного сервера 1С будет напоминать работу клиента, поэтому, приводить его код не имеет смысла. Мы опрашиваем наличие файлов с вопросами, и пока они есть, обрабатывать их, формируя ответы. При этом, стоит следить, чтобы не обработанные клиентами ответы не затирались.
Но, говоря о применении 1С в качестве серверной программы, мне хотелось бы акцентировать внимание на замене им mysql и xml. По сути, используя 1С, мы имеем мощнейший инструмент обработки данных. Намного более мощный, чем mysql. Ни что также не мешает нам заменить xml-шаблоны модулем генерации страничек в составе все того же нашего 1С. Соответственно, при таком подходе php-код обработки Интернет запросов уменьшится до минимума. Это разгрузит модуль обмена данными с клиентами, и увеличит пропускную способность нашего web-сервера в несколько раз.
Остается вопрос, как более мягко связать web-сервер c 1С? Конечно, можно использовать все те же текстовые файлы обмена. Но в Интернет-варианте это будет выглядеть как-то уж очень топорно. Интересный вариант решения поставленной задачи предлагает сочетание технологии внешних компонент с расширением ISAPI web-сервера. Расширение ISAPI позволяет получать доступ внешнему приложению к серверному потоку данных. Кроме того, в отличие от CGI, ISAPI-библиотека находится в памяти постоянно, а не загружается и выгружается при каждом новом запросе. Это позволит организовать постоянный обмен данными ядра сервера с 1С на высокой скорости.
***
Надеюсь, наш круиз в асинхронные web-дали останется незабываемым, а вариации на тему 1С в рамках асинхронности подарят всем участникам круиза, наблюдавшим свет сверхновой АС-1С, интересные идеи. Только не забывайте чаще стучать по крышке гипердрайва…