Аспектно-ориентированное программирование в JavaScript

JavaScript

Что такое аспектно-ориентированное программирование?

Аспектно-ориентированное программирование (АОП) — это парадигма программирования. Студенты, изучающие веб-интерфейс Java, особенно те, кто использовал Spring, должны быть хорошо знакомы с ним. АОП — одна из важных концепций в среде Spring. Но в Javascript АОП часто упускается из виду.

Сцены

Предположим, у вас есть классное всплывающее окно с календарем.Однажды начальник попросил вас подсчитать количество нажатий на кнопку во всплывающем окне каждый день, поэтому вы сделали захоронение во всплывающем окне;

Через неделю начальник сказал, что пользователи сообщали, что всплывающее окно работало очень медленно и всячески зависало. Вы хотите увидеть среднее время выполнения функции, поэтому добавляете код статистики производительности во всплывающее окно.

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

Тогда существует АОП для решения такого рода проблем.

разделение интересов

Разделение бизнес-кода и кода статистики данных (не бизнес-кода) является одним из классических приложений АОП, независимо от того, на каком языке он написан. Отделение сквозных задач от основных задач является основной концепцией АОП.

Среди общих требований к внешнему интерфейсу есть некоторые компании, которые могут использовать АОП, чтобы отделить их от своих основных задач.

  • Журнал журнала Node.js
  • Закопанные точки, отчетность данных
  • Анализ производительности, статистическое время выполнения функции
  • Динамически добавлять параметры к запросам ajax, динамически изменять параметры функций
  • Отдельный запрос формы и проверка
  • Защита от тряски и дросселирования

Декоратор

Когда дело доходит до АОП, необходимо говорить о шаблоне декоратора, АОП часто путают с шаблоном декоратора.

До ES6+, чтобы использовать шаблон декоратора, обычно черезFunction.prototype.beforeсделать предварительную отделку иFunction.prototype.afterВыполните пост-декорирование (см. «Шаблоны проектирования и методы разработки JavaScript»).

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

Отчет о захороненных точках

Поскольку в фактической разработке с использованием React используется большое количество компонентов на основе классов, я использую React в качестве примера здесь.

Например, на странице есть кнопка, при нажатии на которую открывается всплывающее окно, в то же время требуется отчетность по данным, чтобы подсчитать, сколько пользователей нажали кнопку входа.

import React, { Component } from 'react';
import send from './send';

class Dialog extends Component {

    constructor(props) {
        super(props);
    }

    @send
    showDialog(content) {
        // do things
    }

    render() {
        return (
            <button onClick={() => this.showDialog('show dialog')}>showDialog</button>
        )
    }
}

export default Dialog;

Приведенный выше код относится к@sendDecorator, он изменит метод прототипа в этом классе.@sendРеализация декоратора

export default function send(target, name, descriptor) {
    let oldValue = descriptor.value;

    descriptor.value = function () {
        console.log(`before calling ${name} with`, arguments);
        return oldValue.apply(this, arguments);
    };

    return descriptor;
}

Выполнить после нажатия кнопкиshowDialogДо этого мы можем выполнять нужные операции с аспектами.Мы можем инкапсулировать код, связанный со скрытыми точками и отчетами о данных, в этом декораторе для реализации АОП.

Передняя отделка и задняя отделка

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

function before(beforeFn = function () { }) {
    return function (target, name, descriptor) {
        let oldValue = descriptor.value;

        descriptor.value = function () {
            beforeFn.apply(this, arguments);
            return oldValue.apply(this, arguments);
        };

        return descriptor;
    }
}

Таким образом, мы можем использовать@beforeДекоратор вырезает произвольный код, не относящийся к бизнесу, перед методом-прототипом.

function beforeLog() {
    console.log(`before calling ${name} with`, arguments);
}
class Dialog {
    ...
    @before(beforeLog)
    showDialog(content) {
        // do things
    }
    ...
}

а также@beforeДекораторы похожи и могут реализовать@afterПостдекоратор, но порядок выполнения функций другой.

function after(afterFn = function () { }) {
    return function (target, name, descriptor) {
        let oldValue = descriptor.value;

        descriptor.value = function () {
            let ret = oldValue.apply(this, arguments);
            afterFn.apply(this, arguments);
            return ret;
        };

        return descriptor;
    }
}

анализ производительности

Иногда мы хотим посчитать время выполнения кода на стороне пользователя, но не хотим встраивать управляющий код в бизнес-код, мы также можем использовать декоратор для выполнения АОП.

function measure(target, name, descriptor) {
    let oldValue = descriptor.value;

    descriptor.value = function () {
        let ret = oldValue.apply(this, arguments);
        performance.mark("startWork");
        afterFn.apply(this, arguments);
        performance.mark("endWork");
        performance.measure("work", "startWork", "endWork");
        performance
          .getEntries()
          .map(entry => JSON.stringify(entry, null, 2))
          .forEach(json => console.log(json));
        return ret;
    };

    return descriptor;
}

Добавить перед методом класса, время выполнения которого нужно считать@measureВсе, код для статистики производительности не будет вторгаться в бизнес-код.

class Dialog {
    ...
    @measure
    showDialog(content) {
        // do things
    }
    ...
}

резюме

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

Ссылаться на