Comments 6
Когда мне нужно было организовать асинхронную работу с плагином и определённым порядком выполнения и кешированием некоторых результятов я пошёл по другому пути — «суб-модули» знают только о зависимостях для выполнения своих целях, и только после того как они будут удовлетворены произойдёт запрашиваемое действие.
Например пользователь хочет получить какую-то информацию от плагина. Для этого ему нужно авторизоваться. А для того что бы авторизоваться ему нужна открытая сессия с плагином. А что бы была сессия — нужен инстанс плагина.
Таким образом можно сделать как асинхронное-паралельное выполнение функций, так и асинхронно-последовательное. Кэширование организовано по флагу выполнения фунции, флаг именуется так же как и называется функция.
Так же требуется определённая организация кода внутри функции — она должна сообщать как она исполнилась и с каким результатом. Пока что есть небольшие неувязки, но в целом меня устраивает т.к позволяет довольно гибко дополнять или пошагово выполнять необходимый функционал.
Например пользователь хочет получить какую-то информацию от плагина. Для этого ему нужно авторизоваться. А для того что бы авторизоваться ему нужна открытая сессия с плагином. А что бы была сессия — нужен инстанс плагина.
Немного backbone-style кода
checkPrerequisites : function(required){//required - массив с именами функций, которые требуется выполнить
var res = new $.Deferred(),
tempArr = required.map(function(){return new $.Deferred();});
_.each(tempArr, function(val, i){
if(this.get(required[i])){ //Если метод уже был выполнен(установлен в true)
val.resolve();
}else{//в другом случае ждать пока метод будет выполнен
this.once('change:'+required[i], function(){
var method = this.get(required[i]) ? 'resolve' : 'reject';
val[method]();
});
this[required[i]]();
}
}, this);
$.when.apply($, tempArr).done(function(){
res.resolve();
}).fail(function(){
res.reject();
});
return res;
}
/*Пример вызова*/
this.checkPrerequisites(['selectKey']).done(function(){
//Сделать чё-то полезное
}.bind(this))
Таким образом можно сделать как асинхронное-паралельное выполнение функций, так и асинхронно-последовательное. Кэширование организовано по флагу выполнения фунции, флаг именуется так же как и называется функция.
Так же требуется определённая организация кода внутри функции — она должна сообщать как она исполнилась и с каким результатом. Пока что есть небольшие неувязки, но в целом меня устраивает т.к позволяет довольно гибко дополнять или пошагово выполнять необходимый функционал.
0
Какие преимущества по сравнению с rx библиотеками?
P.S. Примеры выглядят ужасно нечитаемо. Это не production-style код.
Структурировать лучше в виде:
var step1 =…
var step2 =…
var errHandlerStep2 =…
root_as
.add(step1)
.add(step2, errHandlerStep2)
И тогда можно сразу увидеть структуру кода. Это избавит от чтения всего месива, чтобы понять что и почему.
P.S. Примеры выглядят ужасно нечитаемо. Это не production-style код.
Структурировать лучше в виде:
var step1 =…
var step2 =…
var errHandlerStep2 =…
root_as
.add(step1)
.add(step2, errHandlerStep2)
И тогда можно сразу увидеть структуру кода. Это избавит от чтения всего месива, чтобы понять что и почему.
0
Концентрация идёт на бизнес-логику, а не «тактические» подходы как подождать и обработать внешнее событие. Скажем так, другая крайность.
1. Исходную синхронную бизнес-логику можно сравнивать практически diff'ом, игнорируя отступы, после конвертации
2. AsyncSteps объект задаёт своего рода задачу — а-ля асинхронный поток обработки.
2.1. Без лишних проблем можно гарантированно ограничить общее время исполнение шага и всех вложенных шагов просто вызвав as.setTimeout()
2.2. При надобности всю задачу можно аннулировать, не беспокоясь о проблемах освобождения внешних ресурсов, т.к. каждый шаг позволяет установить обработчик отмены
3. Есть возможность хранить переменные состояния. Пример: при получении запроса, можно сохранить всю мета-информацию о нём для дальнейшего использования (отладка, авторизация, логирование т.п.)
Разумеется, основное применение всё же на стороне сервисов, а не в пользовательском интерфейсе. При этом, ни что не мешает использовать тот же Reactive вместе с AsyncSteps (пример внешнего события).
P.S. Я ни в коем случае вас не порицаю, если вам удобнее писать что-то вроде:
1. Исходную синхронную бизнес-логику можно сравнивать практически diff'ом, игнорируя отступы, после конвертации
2. AsyncSteps объект задаёт своего рода задачу — а-ля асинхронный поток обработки.
2.1. Без лишних проблем можно гарантированно ограничить общее время исполнение шага и всех вложенных шагов просто вызвав as.setTimeout()
2.2. При надобности всю задачу можно аннулировать, не беспокоясь о проблемах освобождения внешних ресурсов, т.к. каждый шаг позволяет установить обработчик отмены
3. Есть возможность хранить переменные состояния. Пример: при получении запроса, можно сохранить всю мета-информацию о нём для дальнейшего использования (отладка, авторизация, логирование т.п.)
Разумеется, основное применение всё же на стороне сервисов, а не в пользовательском интерфейсе. При этом, ни что не мешает использовать тот же Reactive вместе с AsyncSteps (пример внешнего события).
P.S. Я ни в коем случае вас не порицаю, если вам удобнее писать что-то вроде:
function do_try(){
call_library();
}
function do_catch( err ){
// handle error
}
try {
do_try();
} catch( e ) {
do_catch( e );
}
0
У меня такое впечатление, что пока никто не задавался вопросом как серьёзную бизнес-логику, вроде финансовых транзакций реального времени перенести на асинхронные рельсы.
Либо кто-то об этом задумывался, но разобравшись в проблеме и осознав сколько граблей можно собрать, просто забыл эту идея как страшный сон.
Либо кто-то об этом задумывался, но разобравшись в проблеме и осознав сколько граблей можно собрать, просто забыл эту идея как страшный сон.
0
Расскажите, какие есть слабые места в существующих тактических решениях и как ваше решение поможет их обойти.
При первом приближении кажется, что это вариация Async.js.
При первом приближении кажется, что это вариация Async.js.
0
Я не берусь быть истиной в последней инстанции, но большинство из существующих подходов:
Моей целью было сделать инструмент, с помощью которого можно в буквально смысле перенести «синхронный» (последовательный) код в асинхронную среду исполнения.
Возьмём типовой пример бизнес логики:
FutoIn AsyncSteps именно и был реализовано как аналогия рабочего потока (точнее даже «лёгкого» потока), который можно реализовать на широко распространённых языках программирования.
Хочу ещё раз отметить, что AsyncSteps — это не самоцель, а концепция решения проблемы написания унифицированного по структуре кода бизнес-логики на разных языках программирования.
Проблема ставится другой концепцией, которая решается в рамках другого проекта: как написать легко масштабируемое асинхронное приложение с повторно используемым кодом, чётко оформленным в компоненты, используя разные технологии разработки. Пример: сначала написать прототип на JavaScript/Python, а потом только отдельные части оптимизировать/сделать более надёжными/развить на Java, C++ или C# без шаманства с «кодом-клеем» или вообще переписыванием уже отлаженных компонентов.
- узкоспециализированы и наполнены специфичным программным интерфейсов определённой среды исполнения
- и/или скудны на обработку ошибок исполнения и инструменты отладки
- и/или в принципе, могут отразить лишь определённеый кусок кода, больше ориентированы прятать громоздкую логику под капот
- и/или в принципе, не предусмотрено понятие ограничения по времени и отмены задачи
- и/или отсутствие какого-то централизованного представления о задаче — всё размазано по локальным переменным
- и/или слабо контролируют правильность использование инструмента
- и/или не представляют концепции написания интерфейса библиотек, которые внутри задают собственные шаги выполнения
Моей целью было сделать инструмент, с помощью которого можно в буквально смысле перенести «синхронный» (последовательный) код в асинхронную среду исполнения.
Возьмём типовой пример бизнес логики:
Создаётся рабочий поток (worker thread), который в цикле обрабатывает поступающие запросы:
1. Устанавливается общее ограничение по времени на обработку одного запроса
2. Обрабатываются входные данные
3. Происходят вызовы в другие системы, каждый со своим ограничением по времени
4. Происходят сравнительно тривиальные вычисления (сложные подразумевают оформление в виде библиотеки со всем вытекающим из этого)
5. Формируются и отсылаются выходные данные
Альтернативно 1:
* Кидается исключение, которое не перехватывается бизнес-логикой
* Освобождаются все ресурсы, связанные с данным запросом
* Ловится исключение и формируется ответ-ошибка
Альтернативно 2:
* Срабатывает ограничение по времени исполнения
* Задача отменяется
* Освобождаются все ресурсы
* Формируется ответ-ошибка
FutoIn AsyncSteps именно и был реализовано как аналогия рабочего потока (точнее даже «лёгкого» потока), который можно реализовать на широко распространённых языках программирования.
Хочу ещё раз отметить, что AsyncSteps — это не самоцель, а концепция решения проблемы написания унифицированного по структуре кода бизнес-логики на разных языках программирования.
Проблема ставится другой концепцией, которая решается в рамках другого проекта: как написать легко масштабируемое асинхронное приложение с повторно используемым кодом, чётко оформленным в компоненты, используя разные технологии разработки. Пример: сначала написать прототип на JavaScript/Python, а потом только отдельные части оптимизировать/сделать более надёжными/развить на Java, C++ или C# без шаманства с «кодом-клеем» или вообще переписыванием уже отлаженных компонентов.
0
Sign up to leave a comment.
FutoIn AsyncSteps: концепция и реализация асинхронной бизнес-логики