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

В этой статье мы рассмотрим некоторые решения распространенных проблем при написании приложений Node.

Зарегистрируйте вывод команды установки npm

Чтобы записать вывод команды npm install, мы можем направить stderr в stdout.

Например, мы можем написать:

npm install 2>&1 | tee log.txt

2>&1 перенаправляет stderr на stdout.

tee читает стандартный вывод и записывает его как в стандартный вывод, так и в один или несколько файлов.

Мы пишем в log.txt, как указано в команде.

Разбор страниц с помощью Node.js и XPath

Чтобы проанализировать HTML с помощью XPath, мы анализируем HTML с помощью parse5.

Он не анализирует его в объект DOM, но он быстрый и совместим с W3C.

Мы можем сериализовать его в XHTML с помощью xmlserializer,

Затем можно использовать xmldom для получения DOM.

И мы используем библиотеку xpath для выполнения наших запросов XPath.

Например, мы можем написать:

const fs = require('mz/fs');
const xpath = require('xpath');
const parse5 = require('parse5');
const xmlSer = require('xmlserializer');
const DOMParser = require('xmldom').DOMParser;
(async () => {
  const html = await fs.readFile('./foo.html');
  const document = parse5.parse(html.toString());
  const xhtml = xmlSer.serializeToString(document);
  const doc = new DOMParser().parseFromString(xhtml);
  const select = xpath.useNamespaces({
    x: "http://www.w3.org/1999/xhtml"
  });
  const nodes = select("/html/body/header/div/div[1]/a[2]", doc);
  console.log(nodes);
})();

Мы импортируем библиотеку fs для чтения файла foo.htmk.

Затем мы анализируем документ с parse5 на объект document.

Затем мы преобразуем HTML в XHTML с помощью метода xmlserializer serializeToString.

Затем мы создаем новый экземпляр DOMParser, анализируя преобразованную строку.

Затем мы создаем объект select с помощью метода userNamespace, чтобы мы могли выбирать элементы DOM с помощью XPath.

Затем мы вызываем select для выбора элементов с помощью XPath.

doc - это объект DOM, возвращенный из DOMParser.

nodes имеет возвращенные узлы.

Кроме того, мы можем использовать библиотеку libxmljs для получения узлов с помощью XPath.

Например, мы можем написать:

const libxmljs = require("libxmljs");
const xml =  `
<?xml version="1.0" encoding="UTF-8"?>'
<root>
  <child foo="bar">
    <grandchild baz="foo">some content</grandchild>
  </child>
  <sibling>with content!</sibling>
</root>`;
const xmlDoc = libxmljs.parseXml(xml);
const gchild = xmlDoc.get('//grandchild');
console.log(gchild.text())

Мы используем libxmljs, передавая строку XML методу parsXml.

Затем мы передаем строку XPath методу get, чтобы получить элемент.

И text будет содержать текст для выбранного узла, то есть some content.

Ошибка записи после завершения на веб-сервере Node.js

Если мы используем модуль net для создания веб-сервера, тогда, когда мы пишем сообщение, мы должны передать обратный вызов в качестве второго аргумента для вызова end на нем.

Например, мы можем написать:

const netSocket = require('net').Socket();
netSocket.connect(9090);
netSocket.write('hello', err => netSocket.end());

Мы вызываем netSocket.end() в обратном вызове второго аргумента, чтобы закрыть сокет после записи сообщения.

Мы должны это сделать, потому что write асинхронный. Нет гарантии, что write будет выполнено до end, поскольку мы не передадим его в обратный вызов.

Так что-то вроде:

const netSocket = require('net').Socket();
netSocket.connect(9090);
netSocket.write('hello');
netSocket.end();

приведет к ошибке «написать после окончания».

Разница между response.setHeader и response.writeHead

response.setHeader позволяет нам установить один заголовок для неявных заголовков.

Если заголовок уже существует, то его значение будет заменено.

Мы можем использовать массив строк для отправки нескольких заголовков с одним и тем же именем.

response.writeHead отправляет заголовок ответа на запрос.

Один метод принимает объект с кодом состояния и заголовками ответа.

Чтобы использовать setHeader, мы можем написать:

const body = "hello world";
response.setHeader("Content-Length", body.length);
response.setHeader("Content-Type", "text/plain");
response.setHeader("Set-Cookie", "type=foo");
response.status(200);

Мы устанавливаем один заголовок ответа с одним setHeader вызовом.

Код состояния устанавливается отдельно с response.status.

С другой стороны, с writeHead мы одновременно устанавливаем коды состояния и заголовки ответа.

Например, мы можем написать:

const body = "hello world";
response.writeHead(200, {
  "Content-Length": body.length,
  "Content-Type": "text/plain",
  "Set-Cookie": "type=foo"
});

Мы устанавливаем код состояния ответа в первом аргументе и все заголовки ответа в объекте во втором аргументе.

Заключение

response.setHeader и response.writeHead разные.

Мы можем анализировать HTML или XML и использовать XPath для запроса узлов.

Чтобы завершить сокет, созданный с помощью net, мы должны вызвать его в обратном вызове, переданном во второй аргумент write.

Мы можем записать npm install ошибки в файл, перенаправив вывод.