Создаём простой сервер и форму для выполнения запроса (часть 2)

Скрипт обработки.
Страница отображения данных игрока.
Шаблонизатор 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

Загрузил приложение в Heroku — ссылка
Инструкция — тут
Код в ветке — server


Опубликовано

в

от

Метки:

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.