Пробег через цикл и интерактивное отображение данных на вызывающей веб-странице
Уважаемые коллеги, задаюсь вопросом: можно ли при помощи PHP/HTML5/JavaScript/CSS или других технологий реализовать "пробег" через PDO-recordset, отображая результаты на вызывающей веб-странице в реальном времени?
Есть результат SQL-запроса SELECT product_id from Products который возвращает 10 записей. Каждый product_id нужно подставить в URL https://api.domain.com/?pid={product_id} и все десять раз передать эту ссылку cURL'у.
То есть cURL должен десять раз в цикле выполнить API-запросы с разыми product_id. И - самое важное (искомое) - всё это должно интерактивно отображаться на веб-странице и желательно с каким-нибудь индикатором прогресса (gauge), в процентах или еще как-то визуализироваться. Или хотя бы в виде текста, например:
Обработано значение {product_id}
Что-то подсказывает мне, что без JavaScript и, возможно, AJAX-запросов тут не обойтись, но пока я не могу представить себе такое решение. Может быть существуют какие-то законченные куски кода/фреймворки, которые реализовывают подобную функциональность. Дюжина моих запросов к англоязычным источникам, к сожалению, не увенчалась успехом.
В настоящее время мне приходится выполнять эту задачу через приложение на Delphi (Object Pascal), которое запускается на Windows и каждый запрос к API выполняется отдельным потоком. Но наверняка ведь существует изящное решение реализовать подобную функциональность непосредственно в браузере.
Ответы (1 шт):
Рабочий вариант на примере готового API (https://swapi.dev):
let progressBar = document.getElementById('progressBar')
let resultField = document.getElementById('resultField')
function loadList(count) {
clear()
let currentPercent = 100 / count
console.log('currentPercent' + currentPercent)
for (let i = 1; i <= count; i++) {
let url = 'https://swapi.dev/api/people/' + i + '/?format=json'
let result = request(url, 'GET')
result.then(data => processResult(data, currentPercent))
}
}
function processResult(data, currentPercent) {
console.log(data)
if (data.name) {
let oldWidth = parseFloat(progressBar.style.width)
progressBar.style.width = oldWidth + currentPercent + '%'
resultField.innerHTML = resultField.innerHTML + '<br>' + data.name
}
}
function request(url, method) {
return fetch(url, {
method: method,
headers: new Headers({
'Accept': 'application/json',
'Content-type': 'application/json',
}),
}).then(r => r.json()).catch(error => console.error(error))
}
function clear() {
progressBar.style.width = '0%'
resultField.innerHTML = ''
}
.progressBarBox {
box-sizing: content-box;
height: 10px;
margin: 20px 0 10px 0;
background: #555;
border-radius: 20px;
padding: 5px;
box-shadow: inset 0 -1px 1px rgba(255, 255, 255, 0.3);
}
.progressBarBox>span {
display: block;
height: 100%;
border-radius: 20px;
background-color: rgb(43, 194, 83);
box-shadow: inset 0 2px 9px rgba(255, 255, 255, 0.3), inset 0 -2px 6px rgba(0, 0, 0, 0.4);
position: relative;
overflow: hidden;
}
body {
background: #333;
text-align: center;
color: #eee;
font-family: system-ui, sans-serif;
}
<h3>Progress Bar SW API</h3>
<label>
Сколько будем загружать (не больше 80):
<input type="number" value="15" id="count" max="80">
</label>
<button onclick="loadList(document.getElementById(`count`).value);">
Загрузить список элементов</button>
<div class="progressBarBox">
<span id='progressBar' style="width: 0.5%"></span>
</div>
<div id="resultField"></div>