Асинхронность при доступе в БД для чтения системной настройки и данных
Cделан запрос в базу данных из клиентского модуля для получения системной настройки:
this.Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(value) { countSettings = value; }, this);
Получены данные из БД отфильтровав их и сравнив с полученным значением из системной настройки ранее, и если значение выпадающего списка periodicity равно "Ежедневно" и количество записей в базе больше чем системной настройке - срабатывает валидация на поле и всплывающее уведомление при попытке сохранения:
message - сообщение для поля валидации;
periodicity - выпадающий список (словарь) в котором есть значение "Ежедневно";
countSettings - ранее полученное значение системной настройки;
concertProgramsCount - количество записей в таблице;
var periodicity = ""; if (this.get("PsPeriodicity")) { periodicity = this.get("PsPeriodicity").displayValue; } var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "PsConcertPrograms" }); esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName"); var esq1Filter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "PsPeriodicity.Name", "Ежедневно"); esq.filters.add("esq1Filter", esq1Filter); esq.getEntityCollection(function(result) { var message = ""; if (result.success) { var concertProgramsCount = result.collection.collection.length; if (periodicity === "Ежедневно" && concertProgramsCount <= countSettings ) { message = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings); } } return message; }, this);
Вывод валидации для поля и при сохранении страницы:
concertHallsValidator: function(message) { var invalidMessage = message; return { fullInvalidMessage: invalidMessage, invalidMessage: invalidMessage }; }
Проблема в том что по отдельности все работает, но когда вместе - вступает в дело асинхронность и все идет не по очереди, а если использую через callback тогда застреваю на замыкании.
Спасибо всем кто окажет помощь в решении проблемы.
Нравится
Prime Source,
нет. стоп. я думал вы прогоняете esq в onEntityInitialized, а потом используете this.$PeriodValidationMessage для проверки. тогда такие варианты:
1) на изменение поля PsPeriodicity запускаете concertHallsValidator. Изменяете this.addColumnValidator("CreatedOn", this.MessageValidator);
2) Используете asyncValidate (вроде так называется метод)
И уберите return. Ну не используется он в асинхронных функциях)
немного не понимаю смысла return из async функции, поэтому вариант такой:
в attributes добавляете
"PeriodValidationMessage": { dataValueType: 1, value: "" }
esq:
var periodicity = ""; if (this.get("PsPeriodicity")) { periodicity = this.get("PsPeriodicity").displayValue; } var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "PsConcertPrograms" }); esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName"); esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "PsPeriodicity.Name", "Ежедневно")); esq.getEntityCollection(function(result) { if (result.success) { var concertProgramsCount = result.collection.collection.length; //считывание сист. настройки Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(countSettings) { //сравнение if (periodicity === "Ежедневно" && concertProgramsCount <= countSettings ) { this.$PeriodValidationMessage = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings); } }, this); } }, this);
валидация
concertHallsValidator: function(message) { var invalidMessage = this.$PeriodValidationMessage; return { fullInvalidMessage: invalidMessage, invalidMessage: invalidMessage }; }
Добрый день,
Каждый борется с асинхронностью своими средствами :)
Как вариант, можно вложить одно в другое: выполнять запросы по очереди, по мере получения ответа из БД. Например перенести вашу логику с esq запросом в колбэк системной настройки.
Тёскин Дмитрий Валерьевич,
Пробовал, тогда return возвращает поздно ответ
concertHallsValidator: function(){ var periodicity = ""; if (this.get("PsPeriodicity")) { periodicity = this.get("PsPeriodicity").displayValue; } this.Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(countSettings) { var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "PsConcertPrograms" }); esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName"); var esq1Filter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "PsPeriodicity.Name", "Ежедневно"); esq.filters.add("esq1Filter", esq1Filter); esq.getEntityCollection(function(result) { var invalidMessage = ""; if (result.success) { var concertProgramsCount = result.collection.collection.length; if (periodicity === "Ежедневно" && concertProgramsCount > countSettings ) { invalidMessage = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings); } } return invalidMessage; }, this); }, this); }, setValidationConfig: function() { this.callParent(arguments); this.addColumnValidator("PsPeriodicity", this.concertHallsValidator); }
Варфоломеев Данила,
Асинхронность не дает
methods: { concertHallsValidator: function(callback){ var periodicity = ""; if (this.get("PsPeriodicity")) { periodicity = this.get("PsPeriodicity").displayValue; } var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "PsConcertPrograms" }); esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName"); esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "PsPeriodicity.Name", "Ежедневно")); esq.getEntityCollection(function(result) { if (result.success) { var concertProgramsCount = result.collection.collection.length; //считывание сист. настройки Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(countSettings) { //сравнение if (periodicity === "Ежедневно" && concertProgramsCount <= countSettings ) { this.$PeriodValidationMessage = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings); } return callback.call(this); }, this); } }, this); }, MessageValidator: function() { var invalidMessage = this.$PeriodValidationMessage; return { fullInvalidMessage: invalidMessage, invalidMessage: invalidMessage }; }, setValidationConfig: function() { // Вызывает инициализацию валидаторов родительской модели представления. this.callParent(arguments); this.addColumnValidator("CreatedOn", this.concertHallsValidator(this.MessageValidator)); } }, }
Prime Source,
нет. стоп. я думал вы прогоняете esq в onEntityInitialized, а потом используете this.$PeriodValidationMessage для проверки. тогда такие варианты:
1) на изменение поля PsPeriodicity запускаете concertHallsValidator. Изменяете this.addColumnValidator("CreatedOn", this.MessageValidator);
2) Используете asyncValidate (вроде так называется метод)
И уберите return. Ну не используется он в асинхронных функциях)
Варфоломеев Данила,
Спасибо большее, помогло отлично asyncValidate. Раньше не знал что этот метод. Вод такой код заработал отлично:
asyncValidate: function(callback, scope) { this.callParent([function(response) { if (!this.validateResponse(response)) { return; } Terrasoft.chain( function(next) { this.validateConcertHalls(function(response) { if (this.validateResponse(response)) { next(); } }, this); }, function(next) { callback.call(scope, response); next(); }, this); }, this]); }, validateConcertHalls: function(callback, scope) { Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(countSettings) { var periodicity = ""; var result = {success: true}; if (this.get("PsPeriodicity")) { periodicity = this.get("PsPeriodicity").displayValue; } var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "PsConcertPrograms" }); esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName"); esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "PsPeriodicity.Name", "Ежедневно")); esq.getEntityCollection(function(response) { if (response.success && periodicity === "Ежедневно" && (!this.isAddMode() && response.collection.getCount() > countSettings) || (this.isAddMode() && response.collection.getCount() >= countSettings)) { result.message = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings); result.success = false; } callback.call(scope || this, result); }, this); }, this); }
Prime Source,
Если ваша функция должна возвращать какие-то значение, то из коллбэка это сделать не получится. В этом случае у вас уже должны быть где-то готовые значения для того, что бы функция валидации могла синхронно выполниться и вернуть значения. Например значение системной настройки можно получить при инициализации страницы и сохранить в атрибуте страницы, т.к. системная настройка скорее всего не будет часто меняться. Значение из esq запроса можно так же получить раньше и сохранить в атрибут, а потом уже при валидации оперировать существующими значениями. Ну или сделать так, как посоветовал Варфоломеев Данила.