Скрипт обработки.
Страница отображения данных игрока.
Шаблонизатор Pug + стили Bootstrap
Загрузка на Heroku
Добавил пакет async и пошаговый запрос по данным игрока в Википедию (на страницу с тектсом ice_hockey и без)
async getPlayerInfo(outerCallback) { const that = this; const res = []; that.handlerWiki.playersCount = 0; const processData = (statusCode, body, counter) => { const data = {statusCode: statusCode, info: null, error: null}; if (statusCode === 200) { if (counter > 1) { that.handlerWiki.playersCount++; that.handlerWiki.playerInfo.push(new Player(that.names)); } that.handlerWiki.setResponseBody(body); that.handlerWiki.init(that, 1, null); data.info = JSON.parse(JSON.stringify(that.handlerWiki.playerInfo)); } else if (statusCode === 404) { that.error = new Error('page not found'); data.error = `Error 404 page not found ${that.urlWiki}`; } else { data.error = `Status ${statusCode} ${that.urlWiki}`; } return data; }; async.waterfall([ async function() { that.setUrl(that.prepareWikiUrl(true), 'wiki'); const {statusCode, body} = await that.request(that.urlWiki); res.push(processData(statusCode, body, 1)); Promise.resolve(); }, async function() { that.setUrl(that.prepareWikiUrl(false), 'wiki'); const {statusCode, body} = await that.request(that.urlWiki); res.push(processData(statusCode, body, 2)); Promise.resolve(); }, ], function(err) { if (err) { res.push({statusCode: 500, info: null, error: `Error parallel request ${err}`}); } outerCallback(res); }); }
Метод для запросов
async request(url) { const result = {statusCode: null, body: ''}; const options = mUrl.parse(url); const lib = (options.protocol && options.protocol === 'https:') ? https : http; return new Promise((resolve, reject) => { const req = lib.request(options, (res) => { let data = ''; result.statusCode = res.statusCode; res.setEncoding('utf8'); res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { // console.info('data:'); result.body = data; resolve(result); }); }); req.on('error', (e) => { console.error(e); reject(result); }); req.end(); }); }
Шаблоны Pug для страниц:
layout.pug макет всех страниц
//- layout.pug doctype html html(lang="en") html head block head meta(charset="UTF-8") meta(http-equiv="X-UA-Compatible", content="IE=edge") meta(name="viewport", content="width=device-width, initial-scale=1") meta(name="description", content="") meta(name="author", content="") title Search NHL players info block styles link(rel="stylesheet", href="../../scripts/bootstrap/4.4.1/css/bootstrap.min.css") body block content block foot #footer.container p !{copyright} block scripts script(src="../../scripts/jquery/3.4.1/jquery.min.js" defer) script(src="../../scripts/jquery/3.4.1/jquery.slim.min.js" defer) script(src="../../scripts/bootstrap/4.4.1/js/bootstrap.min.js" defer)
index.pug главная страница
//- index.pug extends layout.pug block content .container h4= title include searchForm.pug
searchForm.pug модуль формы на главной стрвнице
form(action='/search', method=post) .form-group label(for='playerName') input(type='text', id='playerName', name='playerName', class='form-control form-control-lg') input(type='submit', value='Search', class='btn btn-primary mb-2') br
result.pug отображение результатов
//- result.pug extends layout.pug mixin player(data) .card .card-body h5.card-title= `${data.name} ${data.surname}` if data.height && data.weight && data.born p.card-text strong='Born' span= `\t ${data.born}` p.card-text strong='Height' span= `\t ${data.height} cm` p.card-text strong='Weight' span= `\t ${data.weight} kg` p.card-text strong='Position' span= `\t ${data.position}` p.card-text strong='Shot' span= `\t ${data.shot}` else p.card-text No content provided block content .container h4= title .container for val in data if (val.statusCode == 200) for info in val.info +player(info) else if val.error div(class='alert alert-error', role='error') #{val.error} else div #{val.statusCode} else div(class='alert alert-info', role='alert') There are no values .container a(href="./", class="btn btn-primary", role="button") back
Подправил загрузку страниц и заголовков
const getHeader = () => { if (type === 'search') { HEADERS['Content-Type'] = 'text/html'; HEADERS['Cache-Control'] = 'max-age=31536000'; } else if (type === 'bootstrapcss') { HEADERS['Content-Type'] = 'text/css'; HEADERS['Cache-Control'] = 'max-age=31536000'; } else if (type === 'jquery') { HEADERS['Content-Type'] = 'application/javascript'; HEADERS['Cache-Control'] = 'max-age=31536000'; } else if (type === 'jqueryslim') { HEADERS['Content-Type'] = 'application/javascript'; HEADERS['Cache-Control'] = 'max-age=31536000'; } else if (type === 'bootstrapjs') { HEADERS['Content-Type'] = 'application/javascript'; HEADERS['Cache-Control'] = 'max-age=31536000'; } else { HEADERS['Content-Type'] = 'text/html'; HEADERS['Cache-Control'] = 'max-age=31536000'; } }; const getType = (request) => { if (request.url.indexOf('/search') > -1) { type = 'search'; } else if (request.url.indexOf('bootstrap.min.css') > -1) { type = 'bootstrapcss'; } else if (request.url.indexOf('jquery.min.js') > -1) { type = 'jquery'; } else if (request.url.indexOf('jquery.slim.min.js') > -1) { type = 'jqueryslim'; } else if (request.url.indexOf('bootstrap.min.js') > -1) { type = 'bootstrapjs'; } else { type = 'index'; } }; const prepareHeaders = (request) => { getType(request); getHeader(); return {headers: HEADERS}; }; const getPage = (source) => { let body = ''; if (type === 'index') { body = pug.renderFile('./src/templates/index.pug', { title: 'Input player name', copyright: `poplauki © ${(new Date()).getFullYear()}`, }); } else if (source && type === 'search') { body = pug.renderFile('./src/templates/result.pug', { title: 'Search result', copyright: `poplauki © ${(new Date()).getFullYear()}`, data: source, }); } else if (type === 'bootstrapcss') { body = fs.readFileSync('./scripts/bootstrap/4.4.1/css/bootstrap.min.css', {encoding: 'utf8'}); } else if (type === 'jquery') { body = fs.readFileSync('./scripts/jquery/3.4.1/jquery.min.js', {encoding: 'utf8'}); } else if (type === 'jqueryslim') { body = fs.readFileSync('./scripts/jquery/3.4.1/jquery.slim.min.js', {encoding: 'utf8'}); } else if (type === 'bootstrapjs') { body = fs.readFileSync('./scripts/bootstrap/4.4.1/js/bootstrap.min.js', {encoding: 'utf8'}); } return body; }; const prepareContent = async (request, data) => { getType(request); if (data && request.method === 'POST') { const {playerName} = parse(data); const con = new Connection(playerName); return new Promise(resolve => { con.getPlayerInfo(results => { getType(request); resolve({content: getPage(results)}); }); }); } else if (request.method === 'GET') { getType(request); if (type === 'search') { const {query} = urlM.parse(request.url); const {playerName} = parse(query); const con = new Connection(playerName); return new Promise(resolve => { con.getPlayerInfo(results => { getType(request); resolve({content: getPage(results)}); }); }); } else { return {content: getPage()}; } } else { return {content: null}; } };
Загрузил приложение в Heroku — ссылка
Инструкция — тут
Код в ветке — server
Добавить комментарий