Асинхронность в управляемом интерфейсе 1С




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2026-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

29 Comments

  1. FreeArcher

    Большое спасибо за статью. Долго думал над этой асинхронностью, зачем да почему… А тут все ответы.

    Reply ↓
  2. TokAdm

    Статья очень полезная. Автору спасибо, за то , что разложил «по полочкам» вопросы асинхронного кода.

    Reply ↓
  3. webester

    Фиксин наконец то смог понять, что такое запрет модальных окон и решил написать по этому поводу статью?

    Reply ↓
  4. Gureev

    На сайте ИТС написано, имхо, намного понятнее.

    Reply ↓
  5. fixin

    (4) не скажи, видел я тот ИТС

    (3) когда человек говорит мне про «запрет модальных окон», я смеюсь и отвечаю «блокировка всего интерфейса».

    Reply ↓
  6. ineshyk

    Это не модное явление, а вынужденные меры для нормальной работы веб клиента.

    Reply ↓
  7. webester

    (5)

    когда человек говорит мне про «запрет модальных окон», я смеюсь и отвечаю «блокировка всего интерфейса».

    Да хоть горшком назови. Суть не меняется. Разработчики это называют именно использованием или не использованием «Режима модальных окон».

    не скажи, видел я тот ИТС

    И что не устроило? Очень подробное описание, когда использовать, когда не использовать, для чего это нужно, примеры по типовым ситуациям гораздо более информативные, чем здесь, разобраны разные случаи.

    Reply ↓
  8. vipetrov2

    Асинхронность нужна не для клиент-серверной архитектуры, а для распаралеливания вычислений. Потому что «ВыполнитьДлительнуюОперацию(ВыполнитьДлительнуюОперациюЗавершение)» и «ВыполнитьДлительнуюОперациюЗавершение()» будут запускаться на стороне сервера, при чем здесь клиент? И вообще 1С это один большой костыль для программиста. Просто разработчики платформы внедряют различные шаблоны проектирования, но при этом получают большие накладные расходы, на свои новшества. И при этом, как кто сгладить негативный эффект они и не собираются. Им вообще ни чего не стоить создать синхронные и асинхронные версии функций. Так нет, например, на стороне клиента с файлами можно работать только асинхронно.

    Можно благодаря этой асинхронности сделать индикатор статуса процесса, но опять же за счет слишком трудоемкого процесса обмена между клиент — сервером эта примочка удлинит выполнение на 10-20%.

    Reply ↓
  9. kiv1c

    (5) а подскажите ссылку на ИТС пожалуйста

    Reply ↓
  10. Bukaska

    (9) Может это? http://its.1c.ru/docs/v8nonmodal/

    Reply ↓
  11. fixin

    (7) важно неиназвание, а суть. Без модальных окон нельзя

    .(8) асинхронность можно было сделать прозрачно для программиста 1с на уровне платформы, но платформописатели 1с любят превращать си в ассемблер, излишне напрягая программиста.

    Reply ↓
  12. fixin

    (6) их можно было бы спрятать от программиста в реализации. Незачем программиста нагружать ассемблером

    Reply ↓
  13. starik-2005

    Не хочу придираться к автору, т.к. это, понятное дело, штука бессмысленная. Да и к статье не хочу придираться. Одно понятно — автор вообще не вкурил, что такое асинхронность в контексте «новомодных веяний и в 1С тоже» ))).

    Суть термина сама по себе вводит в заблуждение кого угодно, ибо с точки зрения здравого смысла, асинхронность — это возможность выполнять что-то независимо от чего либо другого. Типа нажал кнопку — запустилась какая-то фоновая байда, которая выполнить все, что нам нужно, а мы при этом можем еще какие-то кнопочки нажимать.

    Но с точки зрения это самой «новомодности», асинхронность — это отсутствие прямой последовательности между командами. Т.е. есть у тебя вопрос пользователю. Синхронность — это когда ты открываешь пользователю диалог с вопросом и ждешь ответа, как соловей лета. Т.е. команды дальше не выполняются, ждется ответ, после которого уже можно посмотреть, что же это самое модальное окно нам вернуло и, соответственно, обработать результат.

    А вот асинхронность — это когда ты показал диалог пользователю, засунул туда callback-функцию и не ждешь, что ответит тебе пользователь, а занимаешься в это время чем-то другим — просто висишь в ожидании событий. Т.е. при асинхронности ответ пользователя вызовет твою callback-функцию, в которую передаст результат, и который в этой самой отдельной функции и нужно обработать.

    А старт длительной операции для получения какого-либо списка (и какой, интересно, идиот сделал получение списка регламентных и фоновых заданий с помощью этого? Стало еще дольше!) — это к асинхронности отношения имеет мало, ибо вместо того, чтобы дернуть calback-функцию формы при получении списка фоновых заданий, приходится висеть в обработке ожидания и мониторить, а не завершилось ли фоновое задание и не нужно ли уже получить список того, что оно нам напилило. Кароче, хрень это, а не асинхронность.

    Никаких претензий к автору — как уж понял, так и слава Богу.

    Reply ↓
  14. fixin

    (13) уважаемый, висеть в новомодном 1с у вас не получится. потому что любые циклы ожидания в новомодном 1с запрещены. В этом и есть смысл новомодной асинхронности, которая коснулась не только интерфейсных функций, но и всех функций, где есть ожидание чего-либо — пользователя, принтера, дисковой подсистемы.

    Так что это еще вопрос кто читал и не понял и понял не так. 😉

    Reply ↓
  15. tailer2

    В отличиЕ от типовой

    но это так, придирки

    а по существу что-то мне здесь не нравится

    вот код из управляемой формы

    и что вы думаете?

    &НаКлиенте
    Процедура ПриОткрытии(Отказ)
    ScrptCtrl= Новый COMОбъект(«MSScriptControl.ScriptControl»);
    ScrptCtrl.Language=»vbscript»;
    // ждет, временный потребитель
    ScrptCtrl.AddCode(«Dim objService, objEventSource, objEvent, strResult
    |Set WinMGMT = GetObject(«»winmgmts:\.
    ootcimv2″»)
    |Set objEventSource = WinMGMT.ExecNotificationQuery («»SEL ECT * FR OM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA ‘Win32_Process’ AND TargetInstance.Name =’notepad.exe'»»)
    |Set objEvent = objEventSource.NextEvent
    |»);
    
    КонецПроцедуры
    

    Показать

    висит, цуко, намертво, пока блокнот не откроешь

    **

    поясню: если выполнить этот скрипт просто файлом из-под винды, винда продолжает работать, как бы и не ждет наступления события

    Reply ↓
  16. starik-2005

    (14)

    Так что это еще вопрос кто читал и не понял и понял не так. 😉

    Ну так я и говорю, что асинхронность — это callback’и, а не фоновые задания, которые и раньше были. Тут Вам не надо ничего понимать — достаточно поверить, ибо попытки что-то Вам объяснить сами знаете чем кончатся — потом поймете.

    В компьютерном программировании, асинхронные событиями являются те, которые возникают независимо от основного потока выполнения программы. Асинхронные действия — действия, выполненные в неблокирующем режиме, что позволяет основному потоку программы продолжить обработку[6].

    Суть тут в том, что есть основной поток, который сгенерировал отображение диалога, при этом основной поток не ждет результата этого диалога, ибо результат обрабатывается в отдельной функции, указанной при открытии этого диалога. То же самое для начала чтения текстового файла, когда он читается независимо от основного потока программы, а после того, как он прочитался, вызывается callback-функция. В итоге нет блокировки ожидания в коде основной программы. Т.е. нет в асинхронном режиме «Результат = Длг.Выбрать()», а есть «Длг.Показать(CallBackFunction);» и продолжение выполнения кода после этого (или выход из процедуры — как будет угодно г-ну программисту). Вот это и есть асинхронность в том понимании, которое связано с «неблокирующим» основной поток выполнением.

    В общем не стоит путать фоновые задания, которые и в 8.0 вроде как были, с той «новомодной» асинхронностью, которая методологически убирает модальность. В вебе не так просто организовать ввод данных в диалог, чтобы дождаться результата — там как раз асинхронные механизмы используются. При вводе данных используются calback’и, и даже при рендеринге каждый кадр рассчитывается через вызов callback-функции, которая в конце каждого кадра дергается. Т.е. рендерим объект, отрабатываем логику (меняем состояние объектов на основании событий и поведения), вызываем callback-функцию для отрисовки следующего кадра, пьем чай…

    ЗЫ: Как пример предела асинхронности можно привести промисы. Вот это и есть тру-асинхронность, до которой 1С еще пилить и пилить (кстати, тут где-то про промисы в коментах к статье про последовательные асинхронные вызовы было, вот пруф).

    Reply ↓
  17. spacecraft

    (15)

    висит, цуко, намертво, пока блокнот не откроешь

    Ну так использован синхронный метод же. Чего ожидали?

    Может переписать под асинхронный метод ExecNotificationQueryAsync?

    Reply ↓
  18. tailer2

    (17) а ведь я утрудил себя и написал «поясню» :(((

    просто запустите этот файлик из-под винды, а потом откройте блокнот

    винда не зависнет 🙂

    Reply ↓
  19. tailer2

    (17) на самом деле здесь помогает (ну, может помочь, не всем) понимание, как устроены «аппаратные» прерывания в компутере

    Reply ↓
  20. spacecraft

    (18) это серьезно сравниваете?

    Тогда прямой путь к изучению что такое ОС и чем отличается от программ.

    При запуске любого приложения создается отдельный поток. Его еще называют основным потоком приложения.

    Reply ↓
  21. tailer2

    если мне будут нужны советы, я спрошу

    Reply ↓
  22. spacecraft

    (21) да я и не давал конкретно вам совет. Просто указал на глупость.

    Reply ↓
  23. tailer2

    :))

    не дождешься

    Reply ↓
  24. spacecraft

    для чистоты эксперимента:

    Запустить этот скрипт в интерпретаторе командной строки без ключевого слова Start.

    Потом уже сравнивать с 1С.

    Reply ↓
  25. ineshyk

    (12) ну, смотря какого программиста.

    Программиста 1С незачем вообще нагружать разделением директив &НаКлиенте, &НаСервере.

    Программист 1С должен знать бух учет, зарплату и макросы писать. Такой себе, «продвинутый бухгалтер».

    Так было раньше, по крайней мере, до управляемого интерфейса.

    Reply ↓
  26. ineshyk

    (8)Вы не правы. Асинхронность в 1С нужна чисто для того, чтобы нормально работать в браузере, так как движок JS’а по другому работать не умеет. И открыть просто-так модальное окно, и сказать всей клиентской среде — замри, в веб клиенте не получится.

    А работа длительных операций вообще никак не связана с асинхронностью: ни логически, ни физически.

    Reply ↓
  27. starik-2005

    (26)

    И открыть просто-так модальное окно, и сказать всей клиентской среде — замри, в веб клиенте не получится.

    Гыгыгы…

    alert(‘Замрем…’);
    Reply ↓
  28. luter-89

    А вопрос перед записью документа? Это ж самый сложный пример, почему не описан? Я изучал по ИТС

    Reply ↓
  29. boln

    (12)

    их можно было бы спрятать от программиста в реализации.

    Если только в 9.0 🙂

    Перерабатывать компилятор восьмерки только ради этого уже никто не будет.

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *