Скрытие детали в карточке во время выполнения асинхронного Get/Post запроса в bpm'online 5.X

В статье Асинхронные запросы в bpm’online 5.X был приведен пример отправки Get/Post запросов со страницы с использование языка JavaScript.
В этой статье хотелось бы рассказать про подводные камни, которые встретились при реализации и как их можно обойти.
Предположим, имеется некий абонент интернет провайдера, у которого есть такие поля, как баланс, MAC-адрес, IP-адрес, состояние, список последних сессий абонента, получение доступных для смены тарифов, получение текущего тарифа абонента. При открытии карточки необходимо получать обновленную информацию от WCF сервиса, отображать её на странице и сохранять в базе данных.
При наличии сложной логики на странице, а именно:

  • применение нескольких асинхронных запросов;
  • обновление значений в контроллах на странице;
  • обновление значений столбцов в DataSource.ActiveRow;
  • обновление записей в базе с помощью класса Update (для того, чтобы при получении обновленной информации от сервиса, например, баланса, сразу записывать его значение в базу, и при последующем открытии карточки, даже если пользователь закрыл страницу не сохранив запись нажав "Отмена", пользователь увидит последние обновленные сведения, полученные от биллинговой системы, до того момента, пока от сервиса не придет новая, обновленная информация о балансе, в противном случае, при отсутствии доступа к данному сервису (пропало интернет соединение), будет отображаться последняя загруженная информация о балансе).

Столь сложная логика на странице может стать причиной ошибок на странице, как, например, ошибка "Сбой при загрузке состояния отображения. Дерево элементов управления, в которое загружается это состояние отображения, должно соответствовать дереву элементов управления, использованному для сохранения состояния отображения при предыдущем запросе. Например, при динамическом добавлении элементов управления те элементы управления, которые были добавлены при обратной передаче, должны по типу и положению соответствовать элементам управления, добавленным при исходном запросе." (скриншот окна с ошибкой ниже).

Данная ошибка возникает при переходе на деталь "Активности", и другие детали, в которые загружается информация, связанная с данной записью. Причем ошибка возникает только во время выполнения асинхронных запросов к сервису, если быть точнее, при получении информации от сервиса, выполняется серверная логика, во время которой и возникает ошибка.
Чтобы избежать данной ошибки, необходимо запретить пользователю переходить на детали, которые вызывают ошибку. Сделать это можно следующим образом.
В БП страницы на событие PageLoadComplete необходимо добавить элемент "Задание сценарий", который добавляет на страницу следующий JavaScript код (данный скрипт должен выполняться перед добавлением скрипта создания самого запроса, т.е. объекта XMLHttpRequest, как было описано в статье):

// объявление глобальных переменных для объектов-запросов
requestUpdateBalance = new XMLHttpRequest();
requestUpdateMacAndSerialNumber = new XMLHttpRequest();
requestUpdateAbonentState = new XMLHttpRequest();
requestGetSessionDetalisation = new XMLHttpRequest();
requestGetAvaliableTariffs = new XMLHttpRequest();
requestGetCurrentTariff = new XMLHttpRequest();

// Функция, позволяющая скрыть/отобразить все детали, следующие за деталью
// "Активности", включая саму эту деталь
function changeVisibleOfTabs(isVisible) {
  for (var i = 0; i PageContainer_DataTabPanel.items.items.length; i++) {
    if (PageContainer_DataTabPanel.items.items[i].caption == 'Активности') {
      for (var j = i; j PageContainer_DataTabPanel.items.items.length; j++) {
        PageContainer_DataTabPanel.items.items[j].tabHeader.setVisible(isVisible);
      }
      break;
    }
  }
}

// скрываем детали перед выполнением запросов
changeVisibleOfTabs(false);

// создаем таймер, который каждые 500мс проверяет, завершились ли все запросы,
// после того, как все запросы завершены, создаем таймер на 2000мс,
// чтобы отработала вся логика на странице, после чего отображаем скрытые детали
var timerCheckIsDone = setInterval(function() {
  if ((requestUpdateBalance != undefined && requestUpdateBalance != null && requestUpdateBalance.readyState == 4) &&
    (requestUpdateMacAndSerialNumber != undefined && requestUpdateMacAndSerialNumber != null && requestUpdateMacAndSerialNumber.readyState == 4) &&
    (requestUpdateAbonentState != undefined && requestUpdateAbonentState != null && requestUpdateAbonentState.readyState == 4) &&
    (requestGetSessionDetalisation != undefined && requestGetSessionDetalisation != null && requestGetSessionDetalisation.readyState == 4) &&
    (requestGetAvaliableTariffs != undefined && requestGetAvaliableTariffs != null && requestGetAvaliableTariffs.readyState == 4) &&
    (requestGetCurrentTariff != undefined && requestGetCurrentTariff != null && requestGetCurrentTariff.readyState == 4)) {
    clearInterval(timerCheckIsDone);
  var timerChangeVisibleOfTabs = setTimeout(function() {
      changeVisibleOfTabs(true); // отображаем детали
    }, 2000);
  }
}, 500);

Важно! После выполнения данного скрипта, необходимо создать объекты запросов, как было показано в статье. Причем объекты запросов должны ссылаться на глобальные переменные, которые мы объявляли в самом начале, т.е. необходимо писать вместо
var request = new XMLHttpRequest();

вот так:
requestUpdateBalance = new XMLHttpRequest();

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

Нравится

Поделиться

0 комментариев
Показать все комментарии