Переходя непосредственно к теме, эта статья немного длинная, в том числе от этапа проектирования до этапа исследования, до этапа реализации и, наконец, до полного освещения этапа тестирования (включая сбор и очистку данных), а также этап PK для сравнения с основными интерфейсными коммуникационными платформами.
Сначала введем некоторые понятия:
- Возможность параллелизма браузера: дизайн браузера определяет мгновенное количество браузеров, открывающих страницу и одновременно отправляющих HTTP-запросы. Есть много причин для такой конструкции, защищающей как браузер, так и сервер. В частности, вы можете использовать ключевые слова Google или Baidu: параллелизм браузера.
2. Количество одновременных запросов браузера на доменные имена серверов:
3. Пул запросов. Подобно пулу соединений с базой данных, он распределяет и управляет соединениями для запросов к базе данных и т. д.
4. Повторное использование запросов. Запросы, чей жизненный цикл закончился, не будут уничтожены и повторно использованы, что уменьшит необходимость повторного обращения за ресурсами к браузеру и уменьшит общие проверки при разработке общих библиотек.
новая функция:пул соединений
Почему вы сделали это в первую очередь:
Последняя итерация оставила пасхалку в конце: в тесте, после отправки запроса, я сохранил запрос в переменной, а затем попытался открыть его заново и обнаружил, что его можно отправить. Любопытство сгубило кошку, я использовал console.time в браузере для расчета времени выполнения этого js-кода и обнаружил, что время использования повторных запросов составляет примерно половину от первого, а то и меньше. Раз он может быть таким хорошим, почему я не могу это остановить. Итак, этот шаг будет извилистым и поворотным...
Исследуйте идеи:
Подтвердите шаг за шагом в соответствии с идеями дизайна в то время:
1. Убедившись, что запрос отправлен, вы можете снова открыть его и отправить. Это гарантирует правильность направления и возможность дальнейшей оптимизации.
2. Во-вторых, для доменного имени количество одновременных запросов, отправляемых браузером, такое же, как показано на рисунке выше, в основном 6, поэтому пул запросов будет настроен на основе максимального количества одновременных подключений браузера, но из-за различий в браузерах количество подключений в пуле подключений будет настроено для настройки
3. Заполнение пула запросов сконфигурированными запросами будет первой задачей. Для объекта XMLHttpRequest основной идеей является создание копии. Текущей поверхностной копии недостаточно, поэтому выполните тест глубокого копирования, чтобы заполнить запрос. . Однако план провалился.
4. Поскольку прототипом объекта запроса является XMLHttpRequest, этот объект достигается API интерфейса браузера для отправки http-запросов через браузер, но глубина скопированного объекта — это объект, объект не реализует интерфейс браузера, умер, не может быть скопирован напрямую после этого я хочу отправить аналогичный запрос на сбор шести пустых соединений запроса пула? Такое поведение абсолютно невозможно простить, так что сделайте следующий шаг исследования
5. Если объект XMLHttpRequest реализует интерфейс браузера, то мы повторно указываем прототип глубоко скопированного объекта на XMLHttpRequest. Можно ли отправить запрос. Затем я проверил это, аси, это незаконный запрос, и я знаком с ответом, responseText и т. Д. В объекте XMLHttpRequest, но я все еще только для чтения. , все незаконно.
6. Я давно был обескуражен, опустошить свой разум и передумать, чтобы решить эту проблему. Ссылаясь на идеи дизайна других подобных пулов запросов, либо инициализировать в начале и создавать соединения в пуле одновременно, либо после того, как каждое установленное соединение используется, оно помещается в пул, и соединение включается после соединение заполнено.пул.
7. Учитывая, что каждая страница на внешнем интерфейсе или количество запросов, которые могут быть отправлены в каждом компоненте, не очень велики, может быть возможно отправить 4-5 запросов по одному маршруту для решения задачи малого бизнеса, которая не может может быть достигнута вообще Базовая конфигурация для запуска пула запросов. Во-вторых, отслеживая производительность страницы с помощью производительности браузера, было обнаружено, что время инициализации составляет всего несколько миллисекунд.По сравнению с ускорением последующего использования, на этот раз оплата за время является очень выгодным бюджетом для последующего использования. Поэтому был выбран первый способ, инициализирующий пул запросов за один раз и ожидающий вызова. Следующее ясное мышление сделало более полный и всеобъемлющий дизайн.
Схема оформления пула запросов:
Слева — раздел «Создать пул запросов»
1. При загрузке библиотечного пула Ajax-JS, определив, открыт ли переключатель запроса, оставлен открытым, затем инициализируйте набор процессов.
2. Создайте пустой запрос на основе глобальной конфигурации --> скопируйте необходимые параметры --> создайте пустой объект XMLHttpRequest --> объедините параметры копирования с пустым объектом --> прочитайте количество конфигураций для создания пула запросов.
3. Поскольку пул запросов — это запрос, сгенерированный на основе глобальной конфигурации, если глобальная конфигурация изменится, это вызовет перезагрузку пула запросов и его повторное создание.
Промежуточный -- время жизни отправки запросов через пул запросов
1. При поступлении запроса сначала определите, включен ли переключатель.Если он включен, сначала определите, существует ли еще количество запросов в пуле запросов.
2. Сравните параметры, чтобы увидеть, есть ли изменения в дополнительных предустановленных параметрах (кроме url, data, successEvent, eroorEvent), и если да, то они будут установлены до отправки запроса. (Например: заголовок запроса будет полностью сбрасываться при каждом его открытии)
3. После завершения жизненного цикла запроса пул запросов возвращается. Примечание: В конце жизненного цикла запроса может возникнуть множество ситуаций: отправка неверного URL, тайм-аута и т. д. завершается сбоем на уровне браузера, а при успешной отправке запроса возникают ошибки, отличные от 200, 304 и т. д. таких как ошибки серии 4XX или 5XX, жизненный цикл заканчивается.
4. Наконец, оцените, есть ли запросы в очереди, если они есть, выньте их и вернитесь снова, не возвращаясь напрямую в пул.
Правильно -- система очереди запросов
1. Если запрос превышает количество пулов запросов, пул запросов точно не сможет его выполнить.Даже если он может быть выполнен, браузер фактически ставит эти избыточные параллельные запросы в очередь и ждет окончания волны перед отправкой. Поэтому важно иметь систему очередей для управления запросами.
2. В случае нехватки ресурсов сначала ставьте в очередь. Затем, после того, как жизнь запроса закончится, система очередей будет проверена, чтобы увидеть, есть ли еще запросы в очереди. Во-вторых, если он есть, вынуть его, а потом пройти жизненный цикл запроса.Если он постраничный, то запроса нет.
Фрагмент кода показывает:
- При загрузке библиотеки классов оцените переключатель и инициализируйте код:
var outputObj = function () {
//虽然在IE6、7上可以支持,但是最好升级你的浏览器,毕竟xp已经淘汰,面向未来吧,骚年,和我一起努力吧!!
if (tool.getIEVersion() < 7) {
//实在不想说:升级你的浏览器吧
throw new Error("Sorry,please update your browser.(IE8+)");
}
// 是否开启连接池
if (initParam.pool.isOpen) {
tool.createPool()
}
return tempObj;
};
2. Создать метод
// 创建请求池中链接
createPool: function () {
// IE 系列不支持发送请求传'',所以默认/
tempObj.common({url: '/'}, true)
tool.deepCloneXhr(selfData.xhr, initParam.pool.requestNumber)
},
3. Скопируйте общие параметры в пул запросов
// 拷贝xhr参数
deepCloneXhr: function (data, requestNum) {
var mapping = {
currentUrl: true,
onerror: true,
onload: true,
onreadystatechange: true,
ontimeout: true,
timeout: true, // IE系列只有open连接之后才支持覆盖
withCredentials: true,
xhr_ie8: true
}
var temp = {}
for (var key in data) {
if (mapping[key]) {
if (!isNaN(tool.getIEVersion()) && key !== 'timeout') {
temp[key] = data[key]
} else {
var newKey = '_' + key
temp[newKey] = data[key]
}
}
}
for (var i = 0; i < requestNum; i++) {
var nullRequest = tool.createXhrObject()
tool.MergeObject(nullRequest, temp)
selfData.requestPool.push(nullRequest)
}
},
4. Используйте ускорение, чтобы определить, включено ли оно (только пример поста)
//异步post请求
post: function (url, data, successEvent, errorEvent, timeoutEvent) {
var ajaxParam = {
type: "post",
url: url,
data: data,
contentType: '',
successEvent: successEvent,
errorEvent: errorEvent,
timeoutEvent: timeoutEvent
};
if (initParam.pool.isOpen) {
tool.useRequestPool(ajaxParam)
} else {
tempObj.common(ajaxParam);
}
},
5. Используйте ссылку пула запросов, чтобы установить базовую конфигурацию (url, данные, SuccessEvent).
// 请求池申请请求使用
useRequestPool: function (param) {
// 判断请求池中是否有可用请求
if (selfData.requestPool.length !== 0) {
var temp = selfData.requestPool.shift(), sendData = '', tempHeader = {}
// 赋值操作,将数据捆绑到原型上
temp.callback_success = param.successEvent
temp.callback_error = param.errorEvent
temp.callback_timeout = param.timeoutEvent
temp.data = param.data
// 处理参数
switch (param.contentType) {
case '':
tool.each(tool.MergeObject(param.data, initParam.publicData), function (item, index) {
sendData += (index + "=" + item + "&")
});
sendData = sendData.slice(0, -1);
break
case 'json':
sendData = JSON.stringify(tool.MergeObject(param.data, initParam.publicData))
break
case 'form':
if (!tool.isEmptyObject(initParam.publicData)) {
tool.each(initParam.publicData, function (item, index) {
param.data.append(index, item)
})
}
sendData = param.data
break
}
//判断请求类型
if (param.type === 'get') {
temp.open(param.type, tool.checkRealUrl(param.url, temp) + (sendData === '' ? '' : ('?' + sendData)))
} else {
temp.open(param.type, tool.checkRealUrl(param.url, temp))
}
param.responseType ? (temp.responseType = param.responseType) : null
if (!isNaN(tool.getIEVersion())) {
temp.timeout = temp._timeout
}
switch (param.contentType) {
case '':
tempHeader['Content-Type'] = 'application/x-www-form-urlencoded'
break
case 'json':
tempHeader['Content-Type'] = 'application/json'
break
}
//设置http协议的头部
tool.each(tool.MergeObject(tempHeader, initParam.requestHeader), function (item, index) {
temp.setRequestHeader(index, item)
});
//发送请求
temp.send(param.type === 'get' ? '' : sendData);
} else {
// 没有请求,加载到待发送队列中
selfData.queuePool.push(param)
}
},
6. Повторно использовать ссылки в цикле по умолчанию (onreadystatechange и onload)
//xmlhttprequest每次变化一个状态所监控的事件(可拓展)
xhr.onreadystatechange = function () {
switch (this.readyState) {
case 1://打开
//do something
break;
case 2://获取header
//do something
break;
case 3://请求
//do something
break;
case 4://完成
//在ie8下面,无xhr的onload事件,只能放在此处处理回调结果
if (this.xhr_ie8) {
if (this.status === 200 || this.status === 304) {
if (this.responseType == "json") {
this.callback_success ?
this.callback_success(ajaxSetting.transformResponse(JSON.parse(this.responseText))) :
ajaxSetting.successEvent(ajaxSetting.transformResponse(JSON.parse(this.responseText)))
} else {
this.callback_success ?
this.callback_success(ajaxSetting.transformResponse(this.responseText)) :
ajaxSetting.successEvent(ajaxSetting.transformResponse(this.responseText))
}
} else {
// 请求错误搜集
tool.uploadAjaxError({
type: 'request',
errInfo: JSON.stringify(this.data ? this.data : ajaxSetting.data),
errUrl: this.currentUrl,
errLine: this.status,
Browser: navigator.userAgent
})
}
// 针对IE8 请求池处理
if (ajaxSetting.pool.isOpen) {
tool.responseOver(this)
}
} else {
if (this.status === 0) {
// 发送不存在请求,将不会走onload,直接这里就挂了,请求归还请求池
if (ajaxSetting.pool.isOpen) {
tool.responseOver(this)
}
}
}
break;
}
;
};
//onload事件(IE8下没有该事件)
xhr.onload = function (e) {
if (this.readyState === 4 && (this.status == 200 || this.status == 304)) {
/*
* ie浏览器全系列不支持responseType='json'和response取值,所以在ie下使用JSON.parse进行转换
* */
if (!isNaN(tool.getIEVersion())) {
if (this.responseType === 'json') {
this.callback_success ?
this.callback_success(ajaxSetting.transformResponse(JSON.parse(this.responseText))) :
ajaxSetting.successEvent(ajaxSetting.transformResponse(JSON.parse(this.responseText)));
} else {
this.callback_success ?
this.callback_success(ajaxSetting.transformResponse(this.responseText)) :
ajaxSetting.successEvent(ajaxSetting.transformResponse(this.responseText));
}
} else {
this.callback_success ?
this.callback_success(ajaxSetting.transformResponse(this.response)) :
ajaxSetting.successEvent(ajaxSetting.transformResponse(this.response));
}
} else {
/*
* 这边为了兼容IE8、9的问题,以及请求完成而造成的其他错误,比如404等
* 如果跨域请求在IE8、9下跨域失败不走onerror方法
* 其他支持了Level 2 的版本 直接走onerror
* */
this.callback_error ?
this.callback_error(e.currentTarget.status, e.currentTarget.statusText) :
ajaxSetting.errorEvent(e.currentTarget.status, e.currentTarget.statusText);
// 请求错误搜集
tool.uploadAjaxError({
type: 'request',
errInfo: JSON.stringify(this.data ? this.data : ajaxSetting.data),
errUrl: this.currentUrl,
errLine: this.status,
Browser: navigator.userAgent
})
}
// 生命周期结束之后返回数据池,不绑定状态(是否为成功或失败状态)
if (ajaxSetting.pool.isOpen) {
tool.responseOver(this)
}
};
7. Способ переработки
// 请求周期结束操作
responseOver: function (xhr) {
selfData.requestPool.push(xhr)
if (selfData.queuePool.length > 0) {
var tempData = selfData.queuePool.shift()
tool.useRequestPool(tempData)
}
}
Ниже приводится отображение результатов теста (покрытие теста: тест для основных браузеров без открытия пула запросов, открытие пула запросов, сравнение с ajax основных фреймворков axios и jquery и непрерывная отправка 10, 100, 1000, 5000 запросов для точность сравнения)
хром (тестовая единица: микросекунды):
Firefox (Test Unit: ms) PS: при запросе теста 5000, в дополнение к нормальному открытому пулу запросов может быть, иначе у всех браузер крашится
сафари (тестовая единица: микросекунды):
опера (единица измерения: микросекунды)
край (единица измерения: миллисекунды)
IE11 (единица измерения: миллисекунды)
IE9 (единица измерения: миллисекунды)
IE8 (единица измерения: миллисекунды) PS: если нет запущенного решения под IE8 под axios ie8, jquery не будет проводить тест, а проведет собственный сравнительный тест
Первое утверждение несколько вопросов:
1. Стоимость тестовой единицы
Используйте браузерный метод console.time для получения значения, параметры полученные в разных браузерах разные
2. Почему не согласны со значением
Поскольку ajax-js достигает уровня 0,00X за время, необходимое для открытия пула запросов, то есть уровень микросекунд, который не может быть отображен на линейной диаграмме, поэтому увеличьте единицу, чтобы увидеть тенденцию
Статистические графики, полученные из всех очищенных данных, приведены ниже.:
1. jquery.ajax имеет самую низкую скорость и производительность
2. Когда ajax-js открывает пул запросов, производительность самая лучшая и самая быстрая
3. Библиотека классов ajax-js не открывает пул запросов.Условно говоря, имеет более высокую производительность, чем ajax в jquery.Тем не менее, я должен признать, что axios лучше, чем ajax-js.
4. Когда библиотека классов ajax-js открывает пул запросов, производительность для себя как минимум удваивается, что быстрее чем аксиос, намного быстрее
Данные собираются по адресу:GitHub.com/Джерри — это война Р…
Отчет формируется после очистки данных:GitHub.com/Джерри — это война Р…
Инструменты для очистки данных:GitHub.com/Джерри — это война Р…
Отчет о данных, сформированный после очистки, можно открыть напрямую, и данные можно увидеть более четко.
Если вы хотите протестировать, вы можете перейти на github, чтобы загрузить проект, и написать сервер экспресс-узла под файлом ajax-интерфейса, который можно инициализировать с помощью npm i, а затем запустить с помощью npm run start. Кроме того, в каталоге ajax-testing есть html-файл, в котором представлены тестовые примеры и несколько простых демонстраций.
Все представленные на этот раз методы включают ускорение пула запросов (включение конфигурации глобального ускорения). За исключением общего метода, зарезервируйте общий метод, который не ускоряется, чтобы предотвратить особые потребности. Причем этот пул запросов предназначен только для ускорения одного доменного имени, на втором этапе будет добавлен пул запросов для ускорения разных доменных имен.
адрес гитхаба:GitHub.com/Джерри — это война Р…Чтобы помочь или вдохновить вас, нажмитемаленькие звезды, чтобы поддержать продолжение исследований
У этой итерации есть повороты и повороты, и много раз в середине она не может продолжаться до середины, но поскольку основное направление теста в начале правильное, я не хочу сдаваться, а затем Я выпрямляю свои идеи и иду шаг за шагом, чтобы увидеть себя в конце Что не так, почему мы не можем двигаться в этом направлении. Кроме того, для этого теста мы собирали много данных, постоянно переключаясь с системы Mac на Windows, а также собирали данные для тестирования совместимости и сравнительного тестирования основных платформ для основных браузеров. После завершения сбора терпеливо очистите данные, классифицируйте и суммируйте смешанные данные, затем найдите соответствующий отчет и, наконец, загрузите данные в отчет для более интуитивного отображения.
Процесс непростой, а результаты впечатляют. Несмотря на свои недостатки, axios — отличный фреймворк, и его скорость и производительность определенно хороши. До оптимизации пула запросов написанная мной библиотека не могла достичь такого уровня, но после включения пула запросов он превзошел axios по производительности и скорости, и jquery обсуждаться не будет. В процессе исследования внешнего интерфейса я многому научился, от основы до дизайна, от нижнего уровня до оптимизации, нет проблемы, которую нельзя было бы решить. Признайте себя и станьте лучшей версией себя, нет ничего невозможного.
Переход от 0-1 трудно, собираясь от 99-100 еще сложнее. Однако до тех пор, пока вы это делаете, вы в конечном итоге стану ближе к этому направлению, и передний конец будет поощрять друг друга! !