JS реализует апплет мониторинга WeChat

внешний интерфейс JavaScript Апплет WeChat Ajax

адрес блога

«Упаковка собственных разработанных библиотек JS с использованием модульных инструментов»Как упоминалось в статье, в то время необходимо было написать SDK для мониторинга фоновых обращений к интерфейсу и страничных ошибок апплета.Сегодня поговорим о принципе реализации!

принцип

Я также делал отчеты о скрытых точках данных SDK на веб-стороне браузера. Фактически, принцип аналогичен: путем захвата исходного метода получаются данные для отчета, и, наконец, исходный метод выполняется, так что бесследная погребенная точка может быть реализована.

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

Обычно мы разрабатываем и отправляем ajax с помощью упакованных библиотек, таких как jQuery, Axios и т. д. Однако эти библиотеки по-прежнему используют собственный объект браузера XMLHttpRequest внизу, поэтому нам нужно только изменить объект XMLHttpRequest.

Примечание. Из-за гибкости JS нативные методы легко модифицировать, однако это не рекомендуется!

// 把这段代码放在所有JS代码之前,我们就实现了拦截ajax的需求
window.XMLHttpRequest.prototype.open = (function(originOpen) {
    return function(method, url, async) {
        
        console.log('发送了ajax,url是: ', url);

        return originOpen.apply(this, arguments);
    };
})(window.XMLHttpRequest.prototype.open);

В эту непосредственную функцию мы поместили нативнуюopenметод переданoriginOpenВременно сохраните его, а затем оберните слой функции снаружи, чтобы реализовать функцию печати и вывода URL-адреса, и, наконец, передайтеoriginOpen.applyПозвольте собственному методу работать, тем самым добившись плавного перехвата.

Апплет мониторинга

Перехват wx.request

Операционная среда апплета неwindowа такжеdocumentобъект, который выставляет толькоwxГлобальный объект, отправка сетевых запросов осуществляется черезwx.requestЭто API, так что нам нужно перехватить на этот разwx.requestметод

Давай попробуем изменитьwx.request

wx.request = function() {
    console.log('66666');
}

В это время консоль сообщит об ошибкеTypeError: Cannot set property request of #<Object> which has only a getter

Это потому что,wx.requestЭто свойство, толькоgetметод безsetметод, мы можем пройтиObject.getOwnPropertyDescriptorпроверять:

const des = Object.getOwnPropertyDescriptor(wx, 'request');

//  des {
//   configurable: true,
//   enumerable: true,
//   get: f(),
//   set: undefined
// }

Мы можем изменить его по-другому:

const originRequest = wx.request;
Object.defineProperty(wx, 'request', {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function() {
        const config = arguments[0] || {};
        const url = config.url;
        console.log('发送了ajax,url是: ', url);

        return originRequest.apply(this, arguments);
    }
});

На этот раз реализована функция перехвата!

Отслеживание исключений

Функция регистрации малых программAppиметь глобальныйonErrorметод, мы можем поместить его в файл ввода апплетаapp.jsСначала зарегистрируйте этот метод:

App({
    onError: function(err) {
        console.log('上报错误啦!');
        wx.request({
            url: 'http://monitor.com/monitor/error',
            data: err
        })
    }
})

App({
    // 其他逻辑
})

Однако следует отметить, что если последующая программа перезапишет onError, ранее зарегистрированная onError будет недействительной.

Решение может быть таким: мы отслеживаем SDK, чтобы выставить интерфейс, и позволяем стороне доступа вызывать наш интерфейс в onError.

App({
  onError: function (err) {
    monitor.notifyError(err)
  }
})

данные отчета

После сбора требуемых данных, конечно же, необходимо сообщить об этом фону. Как сообщить? конечно еще б/уwx.requestпослать запрос.

Вот простойбесконечная петля: Если вы используете пакет, который мы упаковали ранееwx.requestОтчетные данные, то запрос ajax на отчетные данные также будет рассматриваться как обычный запрос ajax, а затем инициировать отчет, так что вперед и назад, бесконечно отправляя данные отчета.

Существуют различные решения, такие как:

план 1

доступен в упаковкеwx.requestКогда будет установлено, что отправленный URL-адрес является интерфейсом отчетов, о нем больше не будет сообщаться.

const originRequest = wx.request;
Object.defineProperty(wx, 'request', {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function() {
        const config = arguments[0] || {};
        const url = config.url;
        if (url.indexOf('http://monitor.com') > -1) {
            // 直接发送请求,不上报
            return originRequest.apply(this, arguments);
        }

        console.log('上报ajax数据啦!');
        wx.request({
            url: 'http://monitor.com/monitor/ajax',
            data: config.data
        })

        return originRequest.apply(this, arguments);
    }
});

Сценарий 2

в упаковкеwx.requestПрежде сохраняйте копию оригиналаwx.requestметод, все запросы отчетов следуют не обернутому методу, а самому примитивному методу.

const myRequest = wx.request;

const wrapRequest = function () {
    const originRequest = wx.request;
    Object.defineProperty(wx, 'request', {
        configurable: true,
        enumerable: true,
        writable: true,
        value: function() {
            const config = arguments[0] || {};
            const url = config.url;
       
            console.log('上报数据啦!');
            // 使用最原始的request方法
            myRequest({
                url: 'http://monitor.com/monitor/ajax',
                data: config.data
            })

            return originRequest.apply(this, arguments);
        }
    });
}

wrapRequest();

что-то другое

Конечно, в фактической разработке больше деталей, таких как аутентификация проекта мониторинга, структура кода SDK, сбор и агрегация данных перед отчетностью и т. д., которые не будут подробно описываться в этой статье.