Лучшая практика для контекстного режима во время выполнения в JS
У меня есть веб-приложение на основе Apache. PHP, JS и JQuery. Все работает отлично.
На стороне клиента в JS/jquery есть небольшая библиотека, предлагающая несколько общих методов обработки списков. В прошлом я использовал обратные вызовы для решения тех немногих проблем, когда эти методы должны были вести себя немного иначе. Таким образом, я могу повторно использовать методы, такие как обработка списков, обработка диалогов и прочее для разных частей приложения. Однако в последнее время количество обратных вызовов, которые мне пришлось пройти, когда я вошел в библиотеку, выросло, и я пытаюсь изменить дизайн:
Вместо того, чтобы указывать все обратные вызовы в качестве аргументов функции, я создал в библиотеке объект центрального каталога. Каждый модуль приложения регистрирует свой собственный вариант обратных вызовов в этот каталог после инициализации. Во время выполнения методы ищут требуемые обратные вызовы в этом каталоге, а не ожидают, что это указано в их списке аргументов. Это очищает вещи довольно много.
Однако у меня есть одна вещь, от которой я до сих пор не могу избавиться: мне требуется один аргумент (я называю это контекстом, режим может быть другим термином), который используется методами для поиска требуемого обратного вызова в каталоге. Этот контекст должен быть передан всем методам. Конечно, лучше, чем всевозможные обратные вызовы, указанные везде, но мне интересно, смогу ли я избавиться от этого последнего. Но где мне указать этот контекст, если не в качестве аргумента метода? Я довольно новичок в JS и jquery, поэтому мне не удалось найти подход к этому. Очевидно, я не хочу использовать глобальные переменные, и, честно говоря, я сомневаюсь, что в любом случае я могу просто сохранить контекст в одной переменной, поскольку из-за всех обработчиков событий и внешних воздействий методы могут вызываться в разных контекстах одновременно время или, по крайней мере, чередование. Так что я думаю, мне нужно что-то ближе к стеку функций. Может быть, я могу просто поместить объект контекста в стек и прочитать его из слоев библиотеки, которые нужно знать? Объект будет удален, когда я снова покину библиотеку. Конечно, существуют и другие подходы.
Вот так много опытных программистов, которые, безусловно, могут дать новичку краткую подсказку, отправную точку, которая приводит к идее, как это реализовать. Как это обычно делается?
Я пытался некоторое время, исследуя arguments.callee.caller
иерархия. Я подумал, что, возможно, я мог бы установить член-прототип внутри вызывающей функции, а затем, когда выполнение пошагово пошло вниз, я мог бы просто проходить вверх по стеку вызовов, пока не найду вызывающего, содержащего такое свойство, и использую это значение как контекст. Однако я также видел продолжающиеся дискуссии, которые раскрывают две вещи: 1.) arguments.callee
кажется обесценившимся и 2.) он кажется действительно дорогим. Так что это не пойдет.
Я также читал об альтернативе Function.caller (которая, кажется, не является устаревшей и намного более эффективной, однако до сих пор мне не удавалось исследовать этот путь...
Как написано в настоящее время, передача контекста / режима просто работает путем указания дополнительного аргумента в вызовах функций. Он содержит уникальную строку, которая используется в качестве ключа при просмотре каталога. Итак, как-то так (не скопировано, а написано в качестве примитивного примера):
<!-- callbacks -->
callback_inner_task_base:function(arg1,arg2){
// do something with args
}
callback_inner_task_spec:function(arg1,arg2){
// do something with args
}
<!-- catalog -->
Catalog.Callback:function(context,slot){
// some plausibility checks...
return Catalog[context][slot];
}
Catalog.base.slot=callback_inner_task_base;
Catalog.spec.slot=callback_inner_task_spec;
<!-- callee -->
do_something:function(arg1,arg2,context){
...
// callback as taken from the catalog
Catalog.Callback(callback,'inner_task')(arg1,arg2);
...
}
<!-- caller -->
init:function(...){
...
do_something('thing-1',thing-2','base');
do_something('thing-1',thing-2','spec');
...
}
1 ответ
Но где мне указать этот контекст, если не в качестве аргумента метода?
- Используйте свойство функции, например
Catalog.Callback.context
- Используйте монаду