Node - От 0 базового до актуального официального сайта предприятия

Node.js

Create by jsliang on 2018-11-8 13:42:42
Recently revised in 2018-12-23 21:59:20

Привет друзья, если вы считаете, что эта статья неплохая, не забудьте поставить лайк или звездочку.Ваши лайки и звездочки мотивируют меня писать все больше и больше интересных статей!Адрес GitHub


【2019-08-16】Привет друзья, потому чтоjsliangБиблиотека документации подверглась рефакторингу, некоторые ссылки на эту статью могут быть битыми, иjsliangУ меня нет сил поддерживать старые статьи на стороне Nuggets, извините за это. Для тех, кому нужно получать последние статьи, щелкните адрес GitHub выше и перейдите в библиотеку документов, чтобы просмотреть скорректированные статьи.


Основное содержание этой статьи

  • Основы Node. Создайте основу для Node, изучив основы Node.
  • Node API — включите службу для предоставления API для внешних вызовов.
  • Подключение узла к MySQL - установите mysql через npm, чтобы реализовать связь с базой данных
  • Фактический бой узла - официальный веб-сайт предприятия начинается с 0, чтобы создать официальный веб-сайт предприятия, на котором можно зарегистрироваться, войти в систему и оставить сообщение.
  • Развертывание узла - Как развернуть облачный сервер, чтобы друзья могли просматривать ваш сайт

Ссылка на эту статью

  • Использование проектов развертывания Node, облачных серверов и доменных имен:Связь
  • Адрес загрузки базового кода Node в этой статье:Связь
  • В этой статье адрес загрузки готового кода Node:Связь

Демонстрация готового продукта

каталог

Чем отличается передок без закидывания от соленой рыбы?

содержание
каталог
2 Предисловие
Три основных обучения
3.1 HTTP — начало работы с узлом
3.2 URL-модуль
3.3 CommonJS
3.4 Пакеты и npm
3.5 фс управление файлами
3.6 фс случай
поток 3,7 фс
3.8 Создание веб-сервера
3.9 Неблокирующий ввод-вывод, управляемый событием
3.10 получить и отправить
3.11 Подключение узла к MySQL
Четыре веб-практики - Официальный веб-сайт предприятия
4.1 Среда программирования
4.2 Внутренний интерфейс
4.3 Функция регистрации
4.4 Функция входа в систему
4.5 Функция сообщения
Интеграция с пятью инструментами
5.1 супервизор — отслеживание изменений узла
5.2 PM2 — Управление процессами узла
6 ссылок
Семь онлайн-развертываний
Восемь резюме

2 Предисловие

Назад к содержанию

  Основная цель этой статьи:

  1. Интеграция Node Foundation и углублениеjsliangПоймите изучение Node и облегчите будущий обзор.
  2. Интегрируйте инструменты Node, чтобы облегчить поиск инструментов, более подходящих для разработки в Node.
  3. Сделайте ссылку для новичков в Node.Если у вас есть вопросы, обращайтесь в группу QQ:798961601в консультации.

Три основы

Назад к содержанию

Десять тысяч высотных зданий чжан поднимаются из земли, и фундаменты должны подниматься сами по себе.

3.1 HTTP — начало работы с узлом

Назад к содержанию

Без дальнейшего ADO давайте начнем с кода:

01_http.js

// 1. 引入 http 模块
var http = require("http");

// 2. 用 http 模块创建服务
/**
 * req 获取 url 信息 (request)
 * res 浏览器返回响应信息 (response)
 */
http.createServer(function (req, res) {
  // 设置 HTTP 头部,状态码是 200,文件类型是 html,字符集是 utf8
  res.writeHead(200, {
    "Content-Type": "text/html;charset=UTF-8"
  });

  // 往页面打印值
  res.write('<h1 style="text-align:center">Hello NodeJS</h1>');

  // 结束响应
  res.end();

}).listen(3000); // 监听的端口

 Итак, как мы можем использовать приведенный выше код?

первый, скопируйте и вставьте приведенный выше код в01_http.jsсередина.
потом, запустите терминал VS Code:Ctrl + ~.
тогда,войтиnode 01_http.jsи нажмите ввод.
наконец,Открытьlocalhost:3000:

 Хорошо, готово, теперь давайте объясним вышеприведенный код один за другим:

  1. первый, нам нужно сначала включить режим феи. О нет, это режим HTTP. Все мы знаем, что старомодные серверные языки, такие как PHP, требуют Apache или Nginx для включения служб HTTP. Однако нашему узлу не нужно:
var http = require("http");
  1. потом, откройте службу HTTP и установите открытый порт:
/**
 * req 获取 url 信息 (request)
 * res 浏览器返回响应信息 (response)
 */
http.createServer(function (req, res) {
  // ... 步骤 3 代码
}).listen(3000); // 监听的端口
  1. тогда, мы устанавливаем HTTP-заголовок, выводим значение на страницу и завершаем ответ:
// 设置 HTTP 头部,状态码是 200,文件类型是 html,字符集是 utf8
res.writeHead(200, {
  "Content-Type": "text/html;charset=UTF-8"
});

// 往页面打印值
res.write('<h1 style="text-align:center">Hello NodeJS</h1>');

// 结束响应 
res.end();
  1. наконец, входим в браузерhttp://localhost:3000/, который получит доступ к службе Node, которую мы открыли для отображения страницы на странице.

  На данный момент вы начали собственное путешествие по Node?

3.2 URL-модуль

Назад к содержанию

 Что такое модуль URL?
 Включаем режим Node в консоли (терминале) и распечатываемurlПосмотри:

  Хороший парень, онUrl,parse,resolve,resolveObject,format,URL,URLSearchParams,domainToASCII,domainToUnicodeСтолько модулей.
  Итак, для чего нужны эти модули?

  Без лишних слов начнем с кода:

02_url.js

// 1. 引入 url 模块
var url = require("url");

// 2. 引入 http 模块
var http = require("http");

// 3. 用 http 模块创建服务
/**
 * req 获取 url 信息 (request)
 * res 浏览器返回响应信息 (response)
 */
http.createServer(function (req, res) {

  // 4. 获取服务器请求
  /**
   * 访问地址是:http://localhost:3000/?userName=jsliang&userAge=23
   * 如果你执行 console.log(req.url),它将执行两次,分别返回下面的信息:
   * /  ?userName=jsliang&userAge=23
   * /  /favicon.ico
   * 这里为了防止重复执行,所以排除 req.url == /favicon.ico 的情况
   */
  if(req.url != "/favicon.ico") {
    
    // 5. 使用 url 的 parse 方法
    /**
     * parse 方法需要两个参数:
     * 第一个参数是地址
     * 第二个参数是 true 的话表示把 get 传值转换成对象
     */ 
    var result = url.parse(req.url, true);
    console.log(result);
    /**
     * Url {
     *   protocol: null,
     *   slashes: null,
     *   auth: null,
     *   host: null,
     *   port: null,
     *   hostname: null,
     *   hash: null,
     *   search: '?userName=jsliang&userAge=23',
     *   query: { userName: 'jsliang', userAge: '23' },
     *   pathname: '/',
     *   path: '/?userName=jsliang&userAge=23',
     *   href: '/?userName=jsliang&userAge=23' }
     */

    console.log(result.query.userName); // jsliang

    console.log(result.query.userAge); // 23
  }

  // 设置 HTTP 头部,状态码是 200,文件类型是 html,字符集是 utf8
  res.writeHead(200, {
    "Content-Type": "text/html;charset=UTF-8"
  });

  // 往页面打印值
  res.write('<h1 style="text-align:center">Hello NodeJS</h1>');

  // 结束响应
  res.end();

}).listen(3000);

  В приведенном выше коде:

первый, мы представляем главного героя главыurlМодуль:

// 1. 引入 url 模块
var url = require("url");

потом, мы вводимhttpМодуль:

// 2. 引入 http 模块
var http = require("http");

тогда, мы создаемhttpмодуль, потому чтоurlмониторинг, требуетhttpАктивация модуля:

// 3. 用 http 模块创建服务
/**
 * req 获取 url 信息 (request)
 * res 浏览器返回响应信息 (response)
 */
http.createServer(function (req, res) {
  // ... 第 4 步、第 5 步代码

  // 设置 HTTP 头部,状态码是 200,文件类型是 html,字符集是 utf8
  res.writeHead(200, {
    "Content-Type": "text/html;charset=UTF-8"
  });

  // 往页面打印值
  res.write('<h1 style="text-align:center">Hello NodeJS</h1>');

  // 结束响应
  res.end();
}).listen(3000);

наконец, мы посещаем адрес, который мы дали:http://localhost:3000/?userName=jsliang&userAge=23, и просмотрите егоurlизparseКак пользоваться модулем, что на выходе:

// 4. 获取服务器请求
/**
  * 访问地址是:http://localhost:3000/?userName=jsliang&userAge=23
  * 如果你执行 console.log(req.url),它将执行两次,分别返回下面的信息:
  * /  ?userName=jsliang&userAge=23
  * /  /favicon.ico
  * 这里为了防止重复执行,所以排除 req.url == /favicon.ico 的情况
  */
if(req.url != "/favicon.ico") {
  
  // 5. 使用 url 的 parse 方法
  /**
    * parse 方法需要两个参数:
    * 第一个参数是地址
    * 第二个参数是 true 的话表示把 get 传值转换成对象
    */ 
  var result = url.parse(req.url, true);
  console.log(result);
  /**
    * Url {
    *   protocol: null,
    *   slashes: null,
    *   auth: null,
    *   host: null,
    *   port: null,
    *   hostname: null,
    *   hash: null,
    *   search: '?userName=jsliang&userAge=23',
    *   query: { userName: 'jsliang', userAge: '23' },
    *   pathname: '/',
    *   path: '/?userName=jsliang&userAge=23',
    *   href: '/?userName=jsliang&userAge=23' }
    */

  console.log(result.query.userName); // jsliang

  console.log(result.query.userAge); // 23
}

  Отсюда видно, что мы можем пройтиquery, чтобы получить поле пути, которое мы хотим.

  Конечно, вышесказанное объясняет толькоparseиспользования, мы можем поместить приведенный выше код вifКод в заявлении полностью очищен. Затем введите следующий контент, чтобы узнатьurlПодробнее о модуле:

  1. Все содержимое модуля URL:
console.log(url);

/**
 * Console:
 { 
   Url: [Function: Url],
    parse: [Function: urlParse], // 获取地址信息
    resolve: [Function: urlResolve], // 追加或者替换地址
    resolveObject: [Function: urlResolveObject],
    format: [Function: urlFormat], // 逆向 parse,根据地址信息获取原 url 信息
    URL: [Function: URL],
    URLSearchParams: [Function: URLSearchParams],
    domainToASCII: [Function: domainToASCII],
    domainToUnicode: [Function: domainToUnicode] 
  }
 */
  1. Как использовать синтаксический анализ
console.log(url.parse("http://www.baidu.com"));
/**
 * Console:
  Url {
    protocol: 'http:',
    slashes: true,
    auth: null,
    host: 'www.baidu.com',
    port: null,
    hostname: 'www.baidu.com',
    hash: null,
    search: null,
    query: null,
    pathname: '/',
    path: '/',
    href: 'http://www.baidu.com/' 
  }
 */
  1. parse принимает аргументы:
console.log(url.parse("http://www.baidu.com/new?name=zhangsan"));

/**
 * Console:
  Url {
    protocol: 'http:',
    slashes: true,
    auth: null,
    host: 'www.baidu.com',
    port: null,
    hostname: 'www.baidu.com',
    hash: null,
    search: '?name=zhangsan',
    query: 'name=zhangsan',
    pathname: '/new',
    path: '/new?name=zhangsan',
    href: 'http://www.baidu.com/new?name=zhangsan' 
  }
 */
  1. formatиспользование:
console.log(url.format({
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'www.baidu.com',
  port: null,
  hostname: 'www.baidu.com',
  hash: null,
  search: '?name=zhangsan',
  query: 'name=zhangsan',
  pathname: '/new',
  path: '/new?name=zhangsan',
  href: 'http://www.baidu.com/new?name=zhangsan' 
}))

// Console:
// http://www.baidu.com/new?name=zhangsan
  1. resolveиспользование:
console.log(url.resolve("http://www.baidu.com/jsliang", "梁峻荣"));

// Console:
// http://www.baidu.com/梁峻荣

Конечно,urlЗдесь мы объясняем только введение, для получения дополнительной информации, пожалуйста, обратитесь к официальному веб-сайту API:URL | Node.js v10.14.1 Документация

3.3 CommonJS

Назад к содержанию

  • Что такое CommonJS?

CommonJS должен сформулировать спецификации для производительности JS. Поскольку в JS нет модульной системы, меньше стандартных библиотек и инструментов управления пакетами, появился CommonJS. Он надеется, что JS может работать где угодно, а не только в браузере, поэтому Назад Конечные языки, такие как Java, C# и PHP, позволяют разрабатывать крупномасштабные приложения.

  • Приложение CommonJS?
  1. Серверное JavaScript-приложение. (узел.js)
  2. инструмент командной строки
  3. Настольное приложение с графическим интерфейсом.
  • CommonJS против Node.js?

 CommonJS — это стандарт модульности, а Node.js — реализация CommonJS (модульности).

  • Модульность в Node.js?
  1. В Node модуль делится на две категории: один модуль Node предлагает, известный как основной модуль, второй модуль, написанный пользователем, модуль становится файлами. Основной модуль во время компиляции Исходный код узла компилируется в бинарный исполняемый файл, поэтому его скорость загрузки самая высокая, например: модуль HTTP, модуль URL, модуль FS; файловый модуль динамически загружается во время выполнения, нам необходимо выполнить анализ Road King, найдите файл, процесс выполнения компилятора ...... так что его скорость основного модуля будет относительно медленнее.
  2. Мы можем извлечь публичные функции из отдельного JS-файла и сохранить их, а затем экспортировать модули через exports или module.exports, когда это необходимо, и импортировать эти модули через require.

  Теперь мы объясним модульность в Node и использование экспорта/требования в трех случаях.

 Давайте сначала проверим следующий каталог:

метод первый:

 Сначала создаем новый03_CommonJS.js,03_tool-add.js,node_modules/03_tool-multiply.js,node_modules/jsliang-module/tools.jsЭти 4 файла/папки.
вpackage.jsonМы пока оставим это в стороне и объясним, как он автоматически генерируется позже.

существует03_tool-add.jsсередина:

03_tool-add.js

// 1. 假设我们文件其中有个工具模块
var tools = {
  add: (...numbers) => {
    let sum = 0;
    for (let number in numbers) {
      sum += numbers[number];
    }
    return sum;
  }
}

/**
 * 2. 暴露模块
 * exports.str = str;
 * module.exports = str;
 * 区别:
 * module.exports 是真正的接口
 * exports 是一个辅助工具
 * 如果 module.exports 为空,那么所有的 exports 收集到的属性和方法,都赋值给了 module.exports
 * 如果 module.exports 具有任何属性和方法,则 exports 会被忽略
 */

// exports 使用方法
// var str = "jsliang is very good!";
// exports.str = str; // { str: 'jsliang is very good!' }

// module.exports 使用方法
module.exports = tools;

  Итак, что означает приведенный выше код?
 На первом этапе мы определяем библиотеку инструментовtools.
  На втором шаге проходимmodules.exportsБудуtoolsЭкспортировано.
По этому мы03_CommonJS.jsв состоянии пройтиrequireИмпортировать с помощью:

var http = require("http");

var tools1 = require('./03_tool-add');

http.createServer(function (req, res) {

  res.writeHead(200, {
    "Content-Type": "text/html;charset=UTF-8"
  });

  res.write('<h1 style="text-align:center">Hello NodeJS</h1>');
  
  console.log(tools1.add(1, 2, 3));
  /**
   * Console:
   * 6
   * 6
   * 这里要记得 Node 运行过程中,它请求了两次,
   * http://localhost:3000/ 为一次,
   * http://localhost:3000/favicon.ico 为第二次
   */
  
  res.end();

}).listen(3000);

  На этом мы закончилиexportsа такжеrequireпервое использование.

Способ второй:

 Когда у нас слишком много файлов модулей, у нас должен быть каталог для хранения этих модулей.Узел очень надежен.Он указывает, что мы можем поместить эти файлы вnode_modulesВ каталоге (все размещаются в этом каталоге, другого сумбурного нейминга не будет).

По этому мыnode_modulesсоздать новый03_tool-multiply.jsфайл со следующим содержимым:

03_tool-multiply.js

var tools = {
  multiply: (...numbers) => {
    let sum = numbers[0];
    for (let number in numbers) {
      sum = sum * numbers[number];
    }
    return sum;
  }
}

module.exports = tools;

  В плане ссылок нам достаточно пройти:

// 如果 Node 在当前目录没找到 tool.js 文件,则会去 node_modules 里面去查找
var tools2 = require('03_tool-multiply');

console.log(tools2.multiply(1, 2, 3, 4));

  Таким образом, вы можете успешно импортировать03_tool-multiply.jsфайл.

Способ третий:

 Если все отдельные файлы потеряны вnode_modules, он будет выглядеть загроможденным, поэтому мы должны определить собственный модуль:jsliang-module, а затем преобразовать нашtools.jsХранится в этом каталоге:

jsliang-module/tools.js

var tools = {
  add: (...numbers) => {
    let sum = 0;
    for (let number in numbers) {
      sum += numbers[number];
    }
    return sum;
  },
  multiply: (...numbers) => {
    let sum = numbers[0];
    for (let number in numbers) {
      sum = sum * numbers[number];
    }
    return sum;
  }
}

module.exports = tools;

  Таким образом, мы определили нашу собственную библиотеку инструментов.
  Но если мы пройдемvar tools3 = require('jsliang-module');Перейдите к импорту, вы обнаружите, что он сообщаетerror, поэтому мы должныjsliang-moduleВ каталоге используйте следующую командную строку для созданияpackage.json

PS E:\MyWeb\node_modules\jsliang-module> npm init --yes

  Таким образом, вjsliang-moduleвpackage.json.
  А мы03_CommonJS.jsПросто процитируйте это:

03_CommonJS.js

var http = require("http");

var tools1 = require('./03_tool-add');

// 如果 Node 在当前目录没找到 tool.js 文件,则会去 node_modules 里面去查找
var tools2 = require('03_tool-multiply');

/**
 * 通过 package.json 来引用文件
 * 1. 通过在 jsliang-module 中 npm init --yes 来生成 package.json 文件
 * 2. package.json 文件中告诉了程序入口文件为 :"main": "tools.js",
 * 3. Node 通过 require 查找 jsliang-module,发现它有个 package.json
 * 4. Node 执行 tools.js 文件
 */
var tools3 = require('jsliang-module');

http.createServer(function (req, res) {

  res.writeHead(200, {
    "Content-Type": "text/html;charset=UTF-8"
  });

  res.write('<h1 style="text-align:center">Hello NodeJS</h1>');
  
  console.log(tools1.add(1, 2, 3));
  console.log(tools2.multiply(1, 2, 3, 4));
  console.log(tools3.add(4, 5, 6));
  /**
   * Console:
   * 6
   * 24
   * 15
   * 6
   * 24
   * 15
   * 这里要记得 Node 运行过程中,它请求了两次,
   * http://localhost:3000/ 为一次,
   * http://localhost:3000/favicon.ico 为第二次
   */
  
  res.end();

}).listen(3000);

  На данный момент мы узнали о различныхexportsа такжеrequireПозиция и концепция модульности Node~

использованная литература:

3.4 Пакеты и npm

Назад к содержанию

 В дополнение к основным модулям, предоставляемым Node, вы также можете настраивать модули и использоватьсторонние модули.
 Сторонние модули в Node состоят из пакетов, которые можно использовать для унифицированного управления группой модулей с взаимозависимостями.

 Итак, если нам нужно использовать какие-то сторонние модули, куда нам обращаться?

  1. Байду. Baidu, чтобы найти соответствующий контент стороннего модуля, который необходимо установить.
  2. официальный сайт нпм. Если вы уже знаете имя пакета или что делает пакет. Затем выполните поиск непосредственно на официальном сайте npm, возможно, вы найдете пакет, который хотите установить быстрее.

  Итак, что такое нпм?
 npm — крупнейшая в мире экосистема с открытым исходным кодом. Мы можем загружать различные пакеты через npm.
  Когда мы установили Node, он по умолчанию установил для вас npm.

  • npm -v: просмотреть версию npm.
  • npm list: просмотрите, какие пакеты npm установлены в текущем каталоге.
  • npm info 模块: просмотр версии и содержимого модуля.
  • npm i 模块@版本号: Установить указанную версию модуля.

  В процессе использования npm для установки пакетов вам могут понадобиться некоторые базовые знания npm:

  • i/install:Установить. использоватьinstallИли это аббревиатураi, оба указывают на то, что вы хотите загрузить пакет.
  • uninstall: Удалить. Если вы обнаружите, что больше не используете этот модуль, вы можете пройтиuninstallУдалите его.
  • g: установить глобально. Указывает, что пакет будет установлен на вашем компьютере, и вы сможете использовать его в любом месте вашего компьютера.
  • --save/-S: имя и номер версии установленного таким образом пакета появятся вpackage.jsonсерединаdependenciesсередина.dependenciesЕго необходимо опубликовать в среде сборки. Например:ElementUIтребуется после развертывания, поэтому передайте-Sформа для установки.
  • --save-dev/-D: имя и номер версии установленного таким образом пакета появятся вpackage.jsonсерединаdevDependenciesсередина.devDependenciesИспользуется только в среде разработки. Например:gulpЭто всего лишь инструмент для сжатия кода и упаковки, он не нужен при запущенной программе, так что через-Dформа для установки.

пример:

  • cnpm i webpack-cli -D
  • npm install element-ui -S

 Итак, с таким количеством npm-пакетов, как мы можем ими управлять?
ответpackage.json.
  Если нам нужно создатьpackage.json, то нам нужно только указать каталог управления пакетами (например,node_modules) со следующими именами:

  • npm init: создать шаг за шагомpackage.json.
  • npm init --yes: Быстрое созданиеpackage.json

  Конечно, из-за внутренней сетевой среды иногда загрузка пакетов через npm может быть очень медленной или напрямую зависать.В настоящее время необходимо установить зеркало Taobao npm: cnpm

  • npm install -g cnpm --registry=https://registry.npm.taobao.org

3.5 фс управление файлами

Назад к содержанию

  В этой главе мы объясняем управление файлами fs:

Чтобы быстро найти одно из следующего, используйтеCtrl + F

  1. fs.statОпределить, является ли это файлом или каталогом
  2. fs.mkdirСоздать каталог
  3. fs.writeFileСоздать файл записи
  4. fs.appendFileдобавить файл
  5. fs.readFileпрочитать файл
  6. fs.readdirчитать каталог
  7. fs.renameПереименовать
  8. fs.rmdirудалить каталог
  9. fs.unlinkУдалить файлы

Каталог файлов этой главы:

первый, мы проходимfs.statПроверьте, является ли чтение файлом или каталогом:

05_fs.js

//  1. fs.stat
let fs = require('fs');
fs.stat('index.js', (error, stats) => {
  if(error) {
    console.log(error);
    return false;
  } else {
    console.log(stats);
    /**
     * Console:
     * Stats {
     *  dev: 886875,
     *  mode: 33206,
     *  nlink: 1,
     *  uid: 0,
     *  gid: 0,
     *  rdev: 0,
     *  blksize: undefined,
     *  ino: 844424931461390,
     *  size: 284,
     *  blocks: undefined,
     *  atimeMs: 1542847157494,
     *  mtimeMs: 1543887546361.2158,
     *  ctimeMs: 1543887546361.2158,
     *  birthtimeMs: 1542847157493.663,
     *  atime: 2018-11-22T00:39:17.494Z,
     *  mtime: 2018-12-04T01:39:06.361Z,
     *  ctime: 2018-12-04T01:39:06.361Z,
     *  birthtime: 2018-11-22T00:39:17.494Z }
     */

    console.log(`文件:${stats.isFile()}`); 
    // Console:文件:true
    
    console.log(`目录:${stats.isDirectory()}`); 
    // Console:目录:false

    return false;
  }
})

пройти черезConsoleПечатную информацию мы в основном освоилиfs.statэффект.

потом, мы пытаемся пройтиfs.mkdirСоздайте каталог:

05_fs.js

//  2. fs.mkdir
let fs = require('fs');

/**
 * 接收参数
 * path - 将创建的目录路径
 * mode - 目录权限(读写权限),默认 0777
 * callback - 回调,传递异常参数 err
 */
fs.mkdir('css', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("创建目录成功!");
    // Console:创建目录成功!
  }
})

пройти черезnode 05_fs.js, мы обнаружили, что в каталоге есть еще одинcssпапка.

Так,если есть создание,то оно будет удалено.Как удалить созданный каталог? Объясните здесьfs.rmdir:

05_fs.js

//  8. fs.rmdir
let fs = require('fs');

/**
 * 接收参数
 * path - 将创建的目录路径
 * mode - 目录权限(读写权限),默认 0777
 * callback - 回调,传递异常参数 err
 */
fs.rmdir('css', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("创建目录成功!");
    // Console:创建目录成功!
  }
})

пройти черезnode 05_fs.js, мы находим это в каталогеcssПапка удалена.

тогда, мы проходимfs.writeFileдля создания файла записи:

05_fs.js

//  3. fs.writeFile
let fs = require('fs');

/**
 * filename (String) 文件名称
 * data (String | Buffer) 将要写入的内容,可以是字符串或者 buffer 数据。
 * · encoding (String) 可选。默认 'utf-8',当 data 是 buffer 时,该值应该为 ignored。
 * · mode (Number) 文件读写权限,默认 438。
 * · flag (String) 默认值 'w'。
 * callback { Function } 回调,传递一个异常参数 err。
 */
fs.writeFile('index.js', 'Hello jsliang', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log('写入成功!');
  }
})

 Стоит отметить, что такая запись заключается в очистке всех данных в исходном файле, а затем добавленииHello jsliangЭто предложение. То есть: если он есть, то он будет перезаписан, а если его нет, то он будет создан.

 Удалить, как только он будет создан, вы можете использовать его, если вам интересноfs.unlinkУдалите файл, опять же, не объясняя слишком много.

теперь, когда, это перезаписываемый файл, так есть ли дополнительный файл? да, использоватьfs.appendFileБар:

05_fs.js

//  4. fs.appendFile
let fs = require('fs');

fs.appendFile('index.js', '这段文本是要追加的内容', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("追加成功");
  }
})

  Таким образом, мы успешно добавили к нему абзац, так чтоindex.jsстал:

index.js

Hello jsliang这段文本是要追加的内容

наверху, мы сделали: добавить, изменить, удалить операции. Тогда маленькие друзья должны хорошо знать, что делать дальше:

  • fs.readFileпрочитать файл
  • fs.readdirчитать каталог

05_fs.js

let fs = require('fs');

// 5. fs.readFile
fs.readFile('index.js', (err, data) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("读取文件成功!");
    console.log(data);
    // Console:
    // 读取文件成功!
    // <Buffer 48 65 6c 6c 6f 20 6a 73 6c 69 61 6e 67 e8 bf 99 e6 ae b5 e6 96 87 e6 9c ac e6 98 af e8 a6 81 e8 bf bd e5 8a a0 e7 9a 84 e5 86 85 e5 ae b9>
  }
})

// 6. fs.readdir 读取目录
fs.readdir('node_modules', (err, data) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("读取目录成功!");
    console.log(data);
    // Console:
    // 读取目录成功!
    // [ '03_tool-multiply.js', 'jsliang-module' ]
  }
})

  Как и выше, мы успешно выполнили чтение файлов и чтение каталогов.

наконец, давайте рассмотрим нашу первоначальную цель:

1. fs.statОпределить, является ли это файлом или каталогом
2. fs.mkdirСоздать каталог
3. fs.writeFileСоздать файл записи
4. fs.appendFileдобавить файл
5. fs.readFileпрочитать файл
6. fs.readdirчитать каталог
7. fs.renameПереименовать
8. fs.rmdirудалить каталог
9. fs.unlinkУдалить файлы

  Отлично, осталось переименовать:

05_fs.js

let fs = require('fs');

// 7. fs.rename 重命名
fs.rename('index.js', 'jsliang.js', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("重命名成功!");
  }
})

Конечно, еслиfs.renameЕсть еще более мощная функция: вырезать

05_fs.js

let fs = require('fs');

// 7. fs.rename 重命名
fs.rename('jsliang.js', 'node_modules/jsliang.js', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("剪切成功!");
  }
})

 ОК, все сделано, теперь директория стала:

3.6 фс случай

Назад к содержанию

  В предыдущей главе мы узналиfsуправление файлами.
  Итак, здесь мы пытаемся использоватьfsСделайте что-нибудь маленькое:

06_fsDemo.js

/**
 * 1. fs.stat 检测是文件还是目录
 * 2. fs.mkdir 创建目录
 * 3. fs.writeFile 创建写入文件
 * 4. fs.appendFile 追加文件
 * 5. fs.readFile 读取文件
 * 6. fs.readdir 读取目录
 * 7. fs.rename 重命名
 * 8. fs.rmdir 删除目录
 * 9. fs.unlink 删除文件
 */

// 1. 判断服务器上面有没有 upload 目录,没有就创建这个目录
// 2. 找出 html 目录下面的所有的目录,然后打印出来

let fs = require('fs');

// 图片上传
fs.stat('upload', (err, stats) => {
  // 判断有没有 upload 目录
  if(err) {
    // 如果没有
    fs.mkdir('upload', (error) => {
      if(error) {
        console.log(error);
        return false;
      } else {
        console.log("创建 upload 目录成功!");
      }
    })
  } else {
    // 如果有
    console.log(stats.isDirectory());
    console.log("有 upload 目录,你可以做更多操作!");
  }
})

// 读取目录全部文件
fs.readdir('node_modules', (err, files) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    // 判断是目录还是文件夹
    console.log(files);

    let filesArr = [];

    (function getFile(i) {
      
      // 循环结束
      if(i == files.length) {
        // 打印出所有目录
        console.log("目录:");
        console.log(filesArr);
        return false;
      }

      // 判断目录是文件还是文件夹
      fs.stat('node_modules/' + files[i], (error, stats) => {

        if(stats.isDirectory()) {
          filesArr.push(files[i]);
        }

        // 递归调用
        getFile(i+1);
        
      })
    })(0)
  }
})

поток 3,7 фс

Назад к содержанию

  Без лишних слов, давайте разбиратьсяfsПоток и его чтение:

// 新建 fs
const fs = require('fs');
// 流的方式读取文件
let fileReadStream = fs.createReadStream('index.js');
// 读取次数
let count = 0;
// 保存数据
let str = '';
// 开始读取
fileReadStream.on('data', (chunk) => {
  console.log(`${++count} 接收到:${chunk.length}`);
  // Console:1 接收到:30
  str += chunk;
})
// 读取完成
fileReadStream.on('end', () => {
  console.log("——结束——");
  console.log(count);
  console.log(str);

  // Console:——结束——
  // 1
  // console.log("Hello World!");
})
// 读取失败
fileReadStream.on('error', (error) => {
  console.log(error);
})

  Здесь мы проходимfsмодульныйcreateReadStreamСоздал поток чтения, затем прочитал файлindex.js, который наконец выводит в консоль:

1 接收到:259
——结束——
1
console.log("尽信书,不如无书;尽看代码,不如删掉这些文件。");
console.log("尽信书,不如无书;尽看代码,不如删掉这些文件。");
console.log("尽信书,不如无书;尽看代码,不如删掉这些文件。");

вconsole.log()Эти три строкиindex.jsтекстовое содержание.

  Затем пробуем грязный депозит:

let fs = require('fs');
let data = 'console.log("Hello World! 我要存入数据!")';

// 创建一个可以写入的流,写入到文件 index.js 中
let writeStream = fs.createWriteStream('index.js');
// 开始写入
writeStream.write(data, 'utf8');
// 写入完成
writeStream.end();
writeStream.on('finish', () => {
  console.log('写入完成!');
  // Console:写入完成
});

Мы открытыindex.js, вы обнаружите, что содержимое внутри становитсяconsole.log("Hello World! 我要存入数据!"), в свою очередь, мы читаем и пишем операции в виде потоков.

3.8 Создание веб-сервера

Назад к содержанию

Здесь мы используем модуль http, модуль url, модуль пути, модуль fs для создания веб-сервера.

 Что такое веб-сервер?
Веб-сервер обычно относится к серверу веб-сайта, который относится к программе, которая находится на компьютере определенного типа в Интернете.Он может предоставлять документы, такие как веб-клиент, такой как браузер, а также может размещать файлы веб-сайта для всего мира. просматривать; скачать мир. В настоящее время тремя наиболее распространенными веб-серверами являются Apache, Nginx и IIS.

  Ниже мы используем Node для создания веб-сервиса:

08_WebService.js

// 引入 http 模块
let http = require("http");

// 引入 fs 模块
let fs = require("fs");

http.createServer((req, res) => {
  // 获取响应路径
  let pathName = req.url;

  // 默认加载路径
  if (pathName == "/") {
    // 默认加载的首页
    pathName = "index.html";
  }

  // 过滤 /favicon.ico 的请求
  if (pathName != "/favicon.ico") {
    // 获取 08_WebService 下的 index.html
    fs.readFile("./08_WebService/" + pathName, (err, data) => {
      if (err) {
        
        // 如果不存在这个文件
        
        console.log("404 Not Found!");
        fs.readFile('./08_WebService/404.html', (errorNotFound, dataNotFound) => {
          if(errorNotFound) {
            console.log(errorNotFound);
          } else {
            res.writeHead(200, {
              "Content-Type": "text/html; charset='utf-8'"
            });
            // 读取写入文件
            res.write(dataNotFound);
            // 结束响应
            res.end();
          }
        })
        return;
      } else {

        // 返回这个文件
        
        // 设置请求头
        res.writeHead(200, {
          "Content-Type": "text/html; charset='utf-8'"
        });
        // 读取写入文件
        res.write(data);
        // 结束响应
        res.end();
      }
    });
  }
}).listen(8080);

  Таким образом набираем в браузереlocalhost:8080То есть вы можете увидеть:

 Чувак, это заряжает все чувстваindex.htmlФайлы, даже CSS, разве их не ввели?
  Итак, следующий шаг, мы хотим динамически загружатьhtml,cssтак же какjs:

08_WebService.js

// 引入 http 模块
let http = require("http");

// 引入 fs 模块
let fs = require("fs");

// 引入 url 模块
let url = require("url");

// 引入 path 模块
let path = require("path");

http.createServer((req, res) => {
  
  // 获取响应路径
  let pathName = url.parse(req.url).pathname;

  // 默认加载路径
  if (pathName == "/") {
    // 默认加载的首页
    pathName = "index.html";
  }

  // 获取文件的后缀名
  let extName = path.extname(pathName);

  // 过滤 /favicon.ico 的请求
  if (pathName != "/favicon.ico") {
    // 获取 08_WebService 下的 index.html
    fs.readFile("./08_WebService/" + pathName, (err, data) => {
      // 如果不存在这个文件
      if (err) {
        console.log("404 Not Found!");
        fs.readFile(
          "./08_WebService/404.html",
          (errorNotFound, dataNotFound) => {
            if (errorNotFound) {
              console.log(errorNotFound);
            } else {
              res.writeHead(200, {
                "Content-Type": "text/html; charset='utf-8'"
              });
              // 读取写入文件
              res.write(dataNotFound);
              // 结束响应
              res.end();
            }
          }
        );
        return;
      }
      // 返回这个文件
      else {
        // 获取文件类型
        let ext = getExt(extName);

        // 设置请求头
        res.writeHead(200, {
          "Content-Type": ext + "; charset='utf-8'"
        });
        // 读取写入文件
        res.write(data);
        // 结束响应
        res.end();
      }
    });
  }
}).listen(8080);

// 获取后缀名
getExt = (extName) => {
  switch(extName) {
    case '.html': return 'text/html';
    case '.css': return 'text/css';
    case '.js': return 'text/js';
    default: return 'text/html';
  }
}

  Таким образом, при повторном запросе браузер становится:

  Конечно, выше мы только смоделировалиhtml,css,jsТолько эти три типа файлов, нам нужно смоделировать больше типов файлов:

08_ext.json

 代码详情请点击上面的链接

надjsonВ файле мы определяем различные типы файлов.На данный момент каталог файлов выглядит следующим образом:

  В настоящее время нам нужно изменить нашjsфайл, чтобы адаптировать его к различным запросам и ответам:

08_WebService.js

// 引入 http 模块
let http = require("http");

// 引入 fs 模块
let fs = require("fs");

// 引入 url 模块
let url = require("url");

// 引入 path 模块
let path = require("path");

http.createServer((req, res) => {
  
  // 获取响应路径
  let pathName = url.parse(req.url).pathname;

  // 默认加载路径
  if (pathName == "/") {
    // 默认加载的首页
    pathName = "index.html";
  }

  // 获取文件的后缀名
  let extName = path.extname(pathName);

  // 过滤 /favicon.ico 的请求
  if (pathName != "/favicon.ico") {
    // 获取 08_WebService 下的 index.html
    fs.readFile("./08_WebService/" + pathName, (err, data) => {
      // 如果不存在这个文件
      if (err) {
        console.log("404 Not Found!");
        fs.readFile(
          "./08_WebService/404.html",
          (errorNotFound, dataNotFound) => {
            if (errorNotFound) {
              console.log(errorNotFound);
            } else {
              res.writeHead(200, {
                "Content-Type": "text/html; charset='utf-8'"
              });
              // 读取写入文件
              res.write(dataNotFound);
              // 结束响应
              res.end();
            }
          }
        );
        return;
      }
      // 返回这个文件
      else {
        // 获取文件类型
        let ext = getExt(extName);
        console.log(ext);

        // 设置请求头
        res.writeHead(200, {
          "Content-Type": ext + "; charset='utf-8'"
        });
        // 读取写入文件
        res.write(data);
        // 结束响应
        res.end();
      }
    });
  }
}).listen(8080);

// 获取后缀名
getExt = (extName) => {
  // readFile 是异步操作,所以需要使用 readFileSync
  let data = fs.readFileSync('./08_ext.json');
  let ext = JSON.parse(data.toString());
  return ext[extName];
}

  Итак, мы сделали простой веб-сервер.

3.9 Неблокирующий ввод-вывод, управляемый событием

Назад к содержанию

 Серверные языки, такие как Java, PHP или .NET, будут создавать новый поток для каждого клиентского соединения.
 Node не создает новый поток для каждого подключения клиента, а использует только один поток.
 Когда пользователь подключается, запускается внутреннее событие.Благодаря неарендованному вводу-выводу и механизму, управляемому событиями, программа Node является макроскопически параллельной.
 Использование Node, сервера с 8 ГБ ОЗУ, может обрабатывать более 40 000 одновременных подключений пользователей.

  В этой главе мы в основном рассматриваем:

  1. Что такое неблокирующий ввод-вывод Node?
  2. Что такое модуль событий Node?

 Прежде всего, в нашем обычном программировании мы надеемся, что программу можно будет написать построчно в соответствии с нашими пожеланиями:

09_io.js

console.log("1");

console.log("2");

console.log("3");

/**
 * Console:
 * 1
 * 2
 * 3
 */

  Однако это имело неприятные последствия.
 Иногда мы выполняем некоторые асинхронные методы (функции):

09_io.js

console.log("1");

// console.log("2");
let fs = require('fs');
getExt = () => {
  fs.readFile('08_ext.json', (err, data) => {
    console.log("2");
  })
}
getExt();

console.log("3");

/**
 * Console:
 * 1
 * 3
 * 2
 */

  В приведенном выше коде, посколькуfs.readFileявляется асинхронной функцией Node. Итак, программа сначала выполняет 1 и 3, а затем выполняет последнююfs.readFile2 части.

Здесь видно, что Node не будет препятствовать запуску другого кода из-за логической ошибки в одном фрагменте кода.

 Это приводит к проблеме: шаг 3 может не получить результат выполнения шага 2! Это драйвер ввода-вывода Node без аренды.
  Итак, есть ли способ решить эту проблему?
немного!

  1. через функцию обратного вызова
  2. через узелeventsмодуль

  Во-первых, мы решаем эту асинхронную проблему с помощью функции обратного вызова:

09_io.js

let fs = require("fs");

getExt = (callback) => {
  fs.readFile('08_ext.json', (err, data) => {
    callback(data);
  })  
}

getExt( (result) => {
  console.log(result.toString());
})

 Посредством обратных вызовов мы можемgetExtданные извлекаются.

  Затем мы передаем Nodeeventsмодуль для решения этой асинхронной проблемы:

// 引入 fs 模块
let fs = require("fs");

/**
 * Node 事件循环:
 * 1. Node 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。
 * 2. Node 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。
 * 3. Node 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件。
 */

// 引入 events 模块
let events = require("events");
// 实例化事件对象
let EventEmitter = new events.EventEmitter();

getExt = () => {
  fs.readFile('08_ext.json', (err, data) => {
    // 将 data 广播出去
    EventEmitter.emit('data', data.toString());
  })  
};

getExt();

// 监听 data
EventEmitter.on('data', (ext) => {
  console.log(ext);
});

это здесь,EventEmitter.onслушаяdataформа, полученнаяgetExtРезультат внутреннего исполнения.
  Таким образом, мы узнали о событиях ввода-вывода Node иeventsмодуль

3.10 получить и отправить

Назад к содержанию

  Без лишних слов начнем с кода:

index.js

// 加载 http 模块
var http = require('http');

// 虚拟 SQL 读取出来的数据
var items = [];

// 创建 http 服务
http.createServer(function (req, res) {
  
  // 设置跨域的域名,* 代表允许任意域名跨域
  res.setHeader('Access-Control-Allow-Origin', '*');
  // 设置 header 类型
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  // 跨域允许的请求方式
  res.setHeader('Content-Type', 'application/json');

  // 判断请求
  switch (req.method) {
    
    // post 请求时,浏览器会先发一次 options 请求,如果请求通过,则继续发送正式的 post 请求
    case 'OPTIONS':
      res.statusCode = 200;
      res.end();
      break;
    
      // 如果是 get 请求,则直接返回 items 数组
    case 'GET':
      let data = JSON.stringify(items);
      res.write(data);
      res.end();
      break;
      
    // 如果是 post 请求
    case 'POST':
      let item = '';
      // 读取每次发送的数据
      req.on('data', function (chunk) {
        item += chunk;
      });
      // 数据发送完成
      req.on('end', function () {
        // 存入
        item = JSON.parse(item);
        items.push(item.item);
        // 将数据返回到客户端
        let data = JSON.stringify(items);
        res.write(data);
        res.end();
      });
      break;
  }
}).listen(3000)

console.log('http server is start...');

первый, мы загрузилиhttpмодуль и создал службу.
потом, мы устанавливаем метод междоменной обработки, чтобы разрешить междоменную обработку.
тогда, мы выполнили оценочную обработку запроса.Поскольку мы делаем только простое упражнение, мы только оцениваем, является лиgetзапрос илиpostпросить.
наконец, мы возвращаем результат запроса клиенту.

  Выше мы развернули внутренний узел, а как насчет внешней страницы?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-⌃-Compatible" content="ie=edge">
  <title>Node Web</title>

</head>

<body>

  <div id="app">
    <h1>Todo List</h1>
    <ul>
      <li v-for="(item, index) in items" :key="index">{{ item }}</li>
    </ul>
    <input type="text" v-model="item">
    <button @click="postApi">添加</button>
  </div>

  <!-- cdn 引用:Vue 和 Node -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  
  <script>
    new Vue({
      el: document.getElementById('app'),
      data: function () {
        return {
          items: [],
          item: '',
        }
      },
      created() {
        // 进入页面请求数据
        axios.get('http://localhost:3000/').then(res => {
          console.log("\n【API - get 数据】");
          console.log(res);
          this.items = res.data;
        }).catch(function (err) {
          console.log(err)
        })
      },
      methods: {
        // 点击按钮提交数据
        postApi() {
          axios.post('http://localhost:3000/', {
            item: this.item
          }).then(res => {
            console.log("\n【API - post 数据】")
            console.log(res);
            this.items = res.data;
          }).catch(function (err) {
            console.log(err)
          })
        }
      }
    })
  </script>
</body>

</html>

 Вёрстку делали через Vue, запросы интерфейса делали через Axios. Таким образом, операция с данными завершена.

3.11 Подключение узла к MySQL

Назад к содержанию

Для установки MySQL вы можете просмотретьjsliangнаписано:Установка MySQL и графические инструменты

первый, оформляем таблицу через средства визуализации:

имя Типы длина ключ
id int 11 первичный ключ
name varchar 255
age varchar 255

потом, заполняем таблицу:

id name age
1 jslliang 23
2 Лян Цзюньронг 23

тогда, мы устанавливаем пакет для Node для подключения к MySQL:

npm i mysql -D

приходи еще, мы пишем Node'sindex.js:

index.js

var mysql = require('mysql');
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '123456',
  database: 'node'
});

connection.connect();

connection.query('SELECT * FROM user', function (error, results, fields) {
  if (error) throw error;
  console.log(results);
});

connection.end();

наконец, мы проходимnode index.js, откройте сервис:

[ RowDataPacket { id: 1, name: 'jsliang', age: '23' },
  RowDataPacket { id: 2, name: '梁峻荣', age: '23' } ]

  Таким образом, мы завершили подключение Node к MySQL.

 —————— Великолепная разделительная линия ——————

  Конечно, CRUD — это базовая операция серверной части, поэтому здесь мы можем завершить основную функцию CRUD.

 Сначала посмотрите каталог:

  • Добавить поле таблицы

add.js

var mysql = require('mysql');
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '123456',
  database: 'node'
});

connection.connect();

let addSql = "INSERT INTO user(id,name,age) VALUES(0,?,?)";
let addSqlParams = ["jsliang", "23"];

connection.query(addSql, addSqlParams, function (err, res) {
  if (err) {
    console.log("新增错误:");
    console.log(err);
    return;
  } else {
    console.log("新增成功:");
    console.log(res);
  }
});

connection.end();

  Нам просто нужно напрямуюnode add.js, вы можете добавить данные в базу данных.

  • удалить поле таблицы

delete.js

// 连接 MySQL
var mysql = require('mysql');
// MySQL 的连接信息
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '123456',
  database: 'node'
});

// 开始连接
connection.connect();

// 新增的 SQL 语句及新增的字段信息
var delSql = 'DELETE FROM user where id = 2';

// 连接 SQL 并实施语句
connection.query(delSql, function (err, res) {
  if (err) {
    console.log("删除错误:");
    console.log(err);
    return;
  } else {
    console.log("删除成功:");
    console.log(res);
  }
});

// 终止连接
connection.end();
  • Изменить поля таблицы

update.js

// 连接 MySQL
var mysql = require('mysql');
// MySQL 的连接信息
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '123456',
  database: 'node'
});

// 开始连接
connection.connect();

// 新增的 SQL 语句及新增的字段信息
let updateSql = "UPDATE user SET name = ?,age = ? WHERE Id = ?";
let updateSqlParams = ["LiangJunrong", "23", 1];

// 连接 SQL 并实施语句
connection.query(updateSql, updateSqlParams, function (err, res) {
  if (err) {
    console.log("修改错误:");
    console.log(err);
    return;
  } else {
    console.log("修改成功:");
    console.log(res);
  }
});

// 终止连接
connection.end();
  • поля таблицы поиска

read.js

// 连接 MySQL
var mysql = require('mysql');
// MySQL 的连接信息
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '123456',
  database: 'node'
});

// 开始连接
connection.connect();

// 新增的 SQL 语句及新增的字段信息
let readSql = "SELECT * FROM user";

// 连接 SQL 并实施语句
connection.query(readSql, function (err, res) {
  if (err) throw err;
  console.log(res);
});

// 终止连接
connection.end();

  Выше мы преодолели барьеры между Node и MySQL и реализовали добавление, удаление, изменение и проверку данных.

Четыре веб-практики - Официальный веб-сайт предприятия

Назад к содержанию

 Когда мы занимаемся кодовым боем, мы часто сталкиваемся с некоторыми мелочами, такими как: создание логотипа, создание ico, выбор иконок и т.д...

  Это следующиеjsliangЯ обычно сталкиваюсь с этим, если вам это нужно, вы можете отметить его~

  Кроме того, поскольку HTML и CSS не о чем говорить, предпосылкой этой главы являются статические страницы.jsliangОна написана, и друзья могут скачать ее заранее, прежде чем изучать:

4.1 Среда программирования

Назад к содержанию

первый, давайте посмотрим на наш базовый код внешнего интерфейса:адрес

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

потом, проводим внутренний функциональный анализ:

  1. доска объявлений. пользовательские кликидоска объявленийКогда вам нужно определить, вошел ли пользователь в систему или нет. Если пользователь не вошел в систему, перейдите непосредственно кстраница авторизации; если пользователь вошел в систему, показатьстраница доски объявлений.

существуетстраница доски объявлений, есть два интерфейса:

  • Получить содержимое сообщения:ПоискgetMessageИнтерфейс возвращает всю информацию о сообщении. Поскольку ожидается, что информации будет немного, функция пейджинга здесь не реализована. После того, как мелкие партнеры, нуждающиеся в реализации этой функции, могут разработать интерфейс пейджинга.
  • Отправить контент:ПоискsendMessageИнтерфейс отправляет имя пользователя, идентификатор пользователя и содержимое сообщения на серверную часть.

  1. существуетстраница авторизации, есть интерфейс:
  • Авторизоваться:Поискloginинтерфейса, введите имя и пароль, введенные пользователем.

  1. существуетстраница регистрации, есть интерфейс:
  • регистр:Поискregisterинтерфейса, введите имя и пароль, введенные пользователем.

  Исходя из этого, мы можем спроектировать комбинацию интерфейсов передней и задней частей:

документация по интерфейсу

интерфейс Типы параметр возвращенные сообщения
getMessage: получить информацию о сообщении get Нет параметров n записей: id (идентификатор пользователя), user_name (имя пользователя), user_message (содержимое сообщения пользователя), time (время сообщения)
sendMessage: Отправить сообщение post id (идентификатор пользователя), user_name (имя пользователя), user_message (содержимое сообщения пользователя) статус статус
login:Авторизоваться post id (идентификатор пользователя), user_name (имя пользователя), user_password (пароль пользователя) статус статус
register:регистр post id (идентификатор пользователя), user_name (имя пользователя), user_password (пароль пользователя) статус статус

наконец, оформляем таблицу базы данных MySQL:

пользовательская таблица

имя Типы длина ключ
id int 11 первичный ключ
user_name varchar 255
user_password varchar 255
time datetime

таблица сообщений

имя Типы длина ключ
id int 11 первичный ключ
user_message varchar 255
user_id varchar 255 внешний ключ
user_name varchar 255
time datetime

4.2 Внутренний интерфейс

Назад к содержанию

  Прежде чем мы выполним фактическую операцию, давайте подтвердим, можем ли мы написать интерфейс, чтобы мы могли создать новыйtestпапку, положитьindex.htmlиindex.jsПриходите проверить это.

- text
 - index.html
 - index.js

первый, мы заранее устанавливаем внутренний интерфейс для интерфейса, упомянутого в 4.1:

index.js

// 连接 MySQL:先安装 npm i mysql -D
var mysql = require('mysql');
// MySQL 的连接信息
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '123456',
  database: 'nodebase'
});
// 开始连接
connection.connect();

// 引入 http 模块:http 是提供 Web 服务的基础
const http = require("http");

// 引入 url 模块:url 是对用户提交的路径进行解析
const url = require("url");

// 引入 qs 模块:qs 是对路径进行 json 化或者将 json 转换为 string 路径
const qs = require("querystring");

// 用 http 模块创建服务
/**
 * req 获取 url 信息 (request)
 * res 浏览器返回响应信息 (response)
 */
http.createServer(function (req, res) {

  // 设置 cors 跨域
  res.setHeader("Access-Control-Allow-Origin", "*");
  // 设置 header 类型
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  // 跨域允许的请求方式
  res.setHeader('Content-Type', 'application/json');

  if (req.method == "POST") { // 接口 POST 形式

    console.log("\n【POST 形式】");

    // 获取前端发来的路由地址
    let pathName = req.url;

    console.log("\n接口为:" + pathName);

    // 接收发送过来的参数
    let tempResult = "";

    // 数据接入中
    req.addListener("data", function (chunk) {
      tempResult += chunk;
    });

    // 数据接收完成
    req.addListener("end", function () {

      var result = JSON.stringify(qs.parse(tempResult));
      console.log("\n参数为:");
      console.log(result);

      if (pathName == "/sendMessage") { // 提交留言信息

        console.log("\n【API - 提交留言信息】");

      } else if (pathName == "/login") { // 登录

        console.log("\n【API - 登录】");

      } else if (pathName == "/register") { // 注册

        console.log("\n【API - 注册】");

      }
      // 接口信息处理完毕
    })
    // 数据接收完毕

  } else if (req.method == "GET") { // 接口 GET 形式

    console.log("\n【GET 形式】");

    // 解析 url 接口
    let pathName = url.parse(req.url).pathname;

    console.log("\n接口为:" + pathName);

    if (pathName == "/getMessage") { // 获取留言信息

      console.log("\n【API - 获取留言信息】");

    } else if(pathName == "/") { // 首页
      res.writeHead(200, {
        "Content-Type": "text/html;charset=UTF-8"
      });

      res.write('<h1 style="text-align:center">jsliang 前端有限公司服务已开启!</h1><h2 style="text-align:center">详情可见:<a href="https://github.com/LiangJunrong/document-library/blob/master/other-library/Node/NodeBase.md" target="_blank">Node 基础</a></h2>');

      res.end();
    }

  }

}).listen(8888); // 监听的端口

// 获取当前时间
function getNowFormatDate() {
  var date = new Date();
  var year = date.getFullYear(); // 年
  var month = date.getMonth() + 1; // 月
  var strDate = date.getDate(); // 日
  var hour = date.getHours(); // 时
  var minute = date.getMinutes(); // 分
  var second = date.getMinutes(); // 秒
  if (month >= 1 && month <= 9) {
    month = "0" + month;
  }
  if (strDate >= 0 && strDate <= 9) {
    strDate = "0" + strDate;
  }
  // 返回 yyyy-mm-dd hh:mm:ss 形式
  var currentdate = year + "-" + month + "-" + strDate + " " + hour + ":" + minute + ":" + second;
  return currentdate;
}

  По решениюreq.methodпринадлежатьGETещеPOSTform, тем самым определяя загруженный интерфейс:

  • существуетPOST, решение принадлежитОтправить сообщение,Авторизоватьсяещерегистр;
  • существуетGET, чтобы определить, является лиПолучить информацию о сообщении.

в то же время, где мы определяем соединение MySQL иgetNowFormatDateИспользуется для получения текущего времени в следующем формате:2018-12-21 10:03:59

потом, мы используем страницу внешнего интерфейса, чтобы продемонстрировать, можно ли использовать наш интерфейс:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>演示代码</title>
</head>

<body>
  <div>
    <label for="user">用户名</label><input type="text" id="user">
  </div>
  <div>
    <label for="password">密&nbsp;&nbsp;&nbsp;码</label><input type="password" id="password">
  </div>
  <div>
    <button id="register">注册</button>
  </div>

  <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
  <script>
    $(function () {
      // 测试 get 接口
      $.ajax({
        url: "http://localhost:8888/getMessage",
        type: "POST",
        data: {
          username: "jsliang"
        },
        success: function (res) {
          console.log(res);
        },
        error: function (err) {
          console.log(err);
        }
      })

      $("#register").click(function () {
        // 测试 post 接口
        $.ajax({
          url: "http://localhost:8888/login",
          type: "POST",
          data: {
            username: $("#user").val(),
            password: $("#password").val()
          },
          success: function (res) {
            console.log(res);
          },
          error: function (err) {
            console.log(err);
          }
        })
      })
    });
  </script>
</body>

</html>

наконец, мы проходимnode index.js, и открытьindex.html,пройти черезF12Консоль, чтобы увидеть, нормальный ли наш интерфейс:

  Видно, что наши интерфейсы можно настроить нормально, чтобы мы могли подключиться к базе данных и спроектировать эти четыре интерфейса.

Если вы, ребята, чувствуете, что каждый раз, когда вы обновляете код Node, вам нужно перезапустить его сноваnode index.jsчувствую себя хлопотно, вы можете пройтиsupervisorотслеживать изменения в коде Node,supervisorВ установке используются:supervisor

4.3 Функция регистрации

Назад к содержанию

 Очень хорошо, давайте вернемся на страницу имитационного веб-сайта предприятия, готового написать интерфейс и обогатить интерфейс Node.

первый, запускаем фронтенд и Node-сервисы:

  1. Открыть командную строку/терминал

  2. Откройте переднюю часть

  • cd FrontEndCode
  • live-server

Установитьlive-server:npm i live-server -g

  1. открытый бэкэнд
  • cd NodeWeb
  • supervisor index.js

Установитьsupervisor:npm i supervisor -g

потом, мы запускаем интерфейс вызова, щелкнув событие на странице регистрации:

register.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="keywords" content="前端,jsliang,bootstrap,企业建站">
  <meta http-equiv="description" content="jsliang 为你打造最好的企业服务">
  <link rel="shortcut icon" href="./images/favicon.ico" type="image/x-icon" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>注册-jsliang 前端有限公司</title>
  <link rel="stylesheet" href="./css/index.css">
  <link rel="stylesheet" href="./css/bootstrap.min.css">
</head>

<body>
  <!-- 省略 body 中代码,有需要的请前往第四章开头下载查看全部代码 -->

  <script src="./js/jquery-3.3.1.min.js"></script>
  <script src="./js/bootstrap.min.js"></script>
  <script src="./js/islogin.js"></script>
  <script>
    $(function () {
      $("#register-submit").click(function () {

        let userName = $("#userName").val();
        let userPassword = $("#userPassword").val();

        if (!userName) {
          alert("请输入用户名");
          $("#userName").focus();
        } else if (!userPassword) {
          alert("请输入密码");
          $("#userPassword").focus();
        } else if (userName.length > 10) {
          alert("请输入少于 10 位的用户名");
          $("#userName").focus();
        } else if (userPassword.length > 20) {
          alert("请输入少于 20 位的密码");
          $("#userPassword").focus();
        } else {

          // 如果用户输入的没毛病,那就加载接口
          $.ajax({
            url: "http://localhost:8888/register",
            type: 'post',
            dataType: 'json',
            data: {
              username: userName,
              password: userPassword
            },
            success: function (res) {
              console.log(res);
              if (res.code == "0") {
                alert("注册成功,前往登录!");
                window.location.href = "./login.html";
              }
            },
            error: function (err) {
              console.log(err.responseText);
              if (err.responseText == "注册失败,姓名重复!") {
                alert("用户名已被注册!");
              } else if (err.responseText == "注册失败,名额已满!") {
                alert("注册失败,名额已满!");
              } else if (err.responseText == "注册失败,密码为空!") {
                alert("注册失败,密码为空!");
              } else if (err.responseText == "注册失败,姓名过长!") {
                alert("注册失败,姓名过长!");
              } else if (err.responseText == "注册失败,密码过长!") {
                alert("注册失败,密码过长!");
              } else {
                alert("未知错误!");
              }
            }
          })
        }

      })
    })
  </script>
</body>

</html>

  Итак, когда пользователь нажимаетрегистрПри нажатии на кнопку вызывается интерфейс и данные отправляются на серверную часть, в случае успеха всплывает всплывающее окно и происходит переход на страницу входа, если нет, всплывающее окно подсказывает.

тогда, пишем Node.После того как фронтенд вызывает интерфейс, Node определяет, пусты ли эти два параметра.Если нет, то сохраняет данные в БД.

index.js

// ... 其他代码省略,请自行前往章节 4.2 后端接口 获取其他代码

if (pathName == "/sendMessage") { // 提交留言信息

  console.log("\n【API - 提交留言信息】");

} else if (pathName == "/login") { // 登录

  console.log("\n【API - 登录】");

} else if (pathName == "/register") { // 注册

  console.log("\n【API - 注册】");

  result = JSON.parse(result);

  let username = result.username; // 用户名
  let password = result.password; // 密码
  let time = getNowFormatDate(); // 时间

  if (!username) { // 用户名为空
    res.end("注册失败,用户名为空。");
    return;
  } else if (!password) { // 密码为空
    res.end("注册失败,密码为空!");
    return;
  } else if(username.length > 10) { // 姓名过长
    res.end("注册失败,姓名过长!");
    return;
  } else if(password.length > 20) { // 密码过长
    res.end("注册失败,密码过长!");
    return;
  } else {
    
    // 查询 user 表
    // 使用 Promise 的原因是因为中间调用了两次数据库,而数据库查询是异步的,所以需要用 Promise。
    new Promise( (resolve, reject) => {

      // 新增的 SQL 语句及新增的字段信息
      let readSql = "SELECT * FROM user";
      
      // 连接 SQL 并实施语句
      connection.query(readSql, function (error1, response1) {
        
        if (error1) { // 如果 SQL 语句错误
          throw error1;
        } else {
          
          console.log("\nSQL 查询结果:");

          // 将结果先去掉 RowDataPacket,再转换为 json 对象
          let newRes = JSON.parse(JSON.stringify(response1));
          console.log(newRes);

          // 判断姓名重复与否
          let userNameRepeat = false;
          for(let item in newRes) {
            if(newRes[item].user_name == username) {
              userNameRepeat = true;
            }
          }

          // 如果姓名重复
          if(userNameRepeat) {
            res.end("注册失败,姓名重复!");
            return;
          } else if(newRes.length > 300) { // 如果注册名额已满
            res.end("注册失败,名额已满!");
            return;
          } else { // 可以注册
            resolve();
          }
          
        }
      });

    }).then( () => {
      
      console.log("\n第二步:");
      
      // 新增的 SQL 语句及新增的字段信息
      let addSql = "INSERT INTO user(user_name,user_password, time) VALUES(?,?,?)";
      let addSqlParams = [result.username, result.password, time];

      // 连接 SQL 并实施语句
      connection.query(addSql, addSqlParams, function (error2, response2) {
        if (error2) { // 如果 SQL 语句错误
          console.log("新增错误:");
          console.log(error2);
          return;
        } else {
          console.log("\nSQL 查询结果:");
          console.log(response2);

          console.log("\n注册成功!");

          // 返回数据
          res.write(JSON.stringify({
            code: "0",
            message: "注册成功!"
          }));

          // 结束响应
          res.end();
        }
      });

    })
    // Promise 结束
  }
  // 注册流程结束
}

наконец, проверяем успешность выполнения функции:

4.4 Функция входа в систему

Назад к содержанию

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

login.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="keywords" content="前端,jsliang,bootstrap,企业建站">
  <meta http-equiv="description" content="jsliang 为你打造最好的企业服务">
  <link rel="shortcut icon" href="./images/favicon.ico" type="image/x-icon" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>登录-jsliang 前端有限公司</title>
  <link rel="stylesheet" href="./css/index.css">
  <link rel="stylesheet" href="./css/bootstrap.min.css">
</head>

<body>
  
  <!-- 代码省略,有需要的小伙伴请在第四章前言部分下载代码 -->

  <script src="./js/jquery-3.3.1.min.js"></script>
  <script src="./js/bootstrap.min.js"></script>
  <script src="./js/islogin.js"></script>
  <script>
    $(function () {
      $("#login-submit").click(function () {

        let userName = $("#userName").val(); // 用户名
        let userPassword = $("#userPassword").val(); // 密码

        if (!userName) {
          alert("请输入用户名");
          $("#userName").focus();
        } else if (!userPassword) {
          alert("请输入密码");
          $("#userPassword").focus();
        } else if (userName.length > 10) {
          alert("请输入少于 10 位的用户名");
          $("#userName").focus();
        } else if (userPassword.length > 20) {
          alert("请输入少于 20 位的密码");
          $("#userPassword").focus();
        } else {

          $.ajax({
            url: "http://localhost:8888/login",
            type: 'post',
            dataType: 'json',
            data: {
              username: userName,
              password: userPassword
            },
            success: function (res) {
              console.log(res);
              if (res.code == "0") {
                sessionStorage.setItem("id", res.data.id);
                sessionStorage.setItem("userName", res.data.userName);
                alert("登录成功!");
                window.location.href = "./messageBoard.html";
              } else if (res.code == "1") {
                alert("登录失败,密码错误!");
              }
            },
            error: function (err) {
              console.log(err.responseText);
              if (err.responseText == "不存在该用户!") {
                alert("不存在该用户!");
              } else if (err.responseText == "登录失败,用户名为空!") {
                alert("登录失败,用户名为空!");
              } else if (err.responseText == "登录失败,密码为空!") {
                alert("登录失败,密码为空!");
              } else if (err.responseText == "登录失败,姓名过长!") {
                alert("登录失败,姓名过长!");
              } else if (err.responseText == "登录失败,密码过长!") {
                alert("登录失败,密码过长!");
              } else {
                alert("未知错误!");
              }
            }
          })

        }

      })
    })
  </script>
</body>

</html>

 После написания кода фронтенда редактируем код Node:

index.js


// ... 其他代码省略,请自行前往章节 4.2 后端接口 获取其他代码

if (pathName == "/sendMessage") { // 提交留言信息

  console.log("\n【API - 提交留言信息】");

} else if (pathName == "/login") { // 登录

  console.log("\n【API - 登录】");

  result = JSON.parse(result);

  let username = result.username; // 用户名
  let password = result.password; // 密码

  if (!username) { // 用户名为空
    res.end("登录失败,用户名为空!");
    return;
  } else if (!password) { // 密码为空
    res.end("登录失败,密码为空!");
    return;
  } else if(username.length > 10) {
    res.end("登录失败,姓名过长!");
    return;
  } else if(password.length > 20) {
    res.end("登录失败,密码过长!");
    return;
  } else { 
    
    // 新增的 SQL 语句及新增的字段信息
    let readSql = "SELECT * FROM user WHERE user_name  = '" + username + "'";

    // 连接 SQL 并实施语句
    connection.query(readSql, function (error1, response1) {
      if (error1) {
        throw error1;
      } else {
        if(response1 == undefined || response1.length == 0) { // 不存在用户
          res.end("\n不存在该用户!");
          return;
        } else { // 存在用户
          console.log("\n存在该用户!");

          let newRes = JSON.parse(JSON.stringify(response1));
          console.log(newRes);

          if(newRes[0].user_password == password) { // 密码正确
            // 返回数据
            res.write(JSON.stringify({
              code: "0",
              message: "登录成功!",
              data: {
                id: newRes[0].id,
                userName: newRes[0].user_name
              }
            }));

            res.end();
          } else { // 密码错误
            // 返回数据
            res.write(JSON.stringify({
              code: "1",
              message: "登录失败,密码错误!"
            }));

            res.end();
          }
          // 判断密码正确与否完毕
        }
        // 存在用户处理结束
      }
    });
  }
  // 登录步骤结束
} else if (pathName == "/register") { // 注册

  console.log("\n【API - 注册】");

}

 Очень хорошо, фронтенд и бэкенд все написаны, пора проверить реализована ли функция:

4.5 Функция сообщения

Назад к содержанию

 Теперь у нас осталась функция сообщения, давайте сделаем это за один раз!

messageBoard.html

<!-- 留言板 -->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="keywords" content="前端,jsliang,bootstrap,企业建站">
  <meta http-equiv="description" content="jsliang 为你打造最好的企业服务">
  <link rel="shortcut icon" href="./images/favicon.ico" type="image/x-icon" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>留言板-jsliang 前端有限公司</title>
  <link rel="stylesheet" href="./css/index.css">
  <link rel="stylesheet" href="./css/bootstrap.min.css">
</head>

<body>
  
  <!-- 代码省略,基础代码请前往本章节前言下载 -->

  <script src="./js/jquery-3.3.1.min.js"></script>
  <script src="./js/bootstrap.min.js"></script>
  <script src="./js/islogin.js"></script>
  <script>
    $(function() {
      
      let userName = sessionStorage.getItem("userName");
      let userId = sessionStorage.getItem("id");
      
      // 查询留言板
      if(userName && userId) { // 如果有存储
        $.ajax({
          url: "http://localhost:8888/getMessage",
          type: 'get',
          dataType: 'json',
          success: function (res) {
            console.log(res);
            let li = ``;
            for(let item in res.data) {
              li = li + `
                <li>
                  <span class="text-warning font-bold">☆ </span>
                  <span class="user-message">${res.data[item].user_message}</span>
                  <span>—— </span>
                  <span class="user-name">${res.data[item].user_name} [${res.data[item].user_id}]</span>
                  <span class="message-time">${res.data[item].time}</span>
                </li>
              `;
            }
            $("#message-board-ul").append(li);
          },
          error: function (err) {
            console.log(err);
          }
        })
      } else { // 如果没有存储
        window.location.href = "../login.html";
      }

      // 提交留言
      $("#message-submit").click(function() {
        let messageText = $("#message").val()
        if(!messageText) {
          alert("留言内容不能为空");
        } else if(messageText.length > 140) {
          alert("留言长度不能超过 140 位!");
        } else {
          $.ajax({
            url: "http://localhost:8888/sendMessage",
            type: 'post',
            dataType: 'json',
            data: {
              userid: userId,
              username: userName,
              message: messageText
            },
            success: function (res) {
              console.log(res);
              if(res.code == "0") {
                alert("新增成功!");
                window.location.reload();
              }
            },
            error: function (err) {
              console.log(err);
              console.log(err.responseText);
              if (err.responseText == "登录失败,留言内容为空!") {
                alert("登录失败,留言内容为空!");
              } else if (err.responseText == "登录失败,字数超过限制!") {
                alert("登录失败,字数超过限制!");
              } else {
                alert("未知错误!");
              }
            }
          })
        }
      })

    })
  </script>
</body>

</html>

  Затем напишите бэкэнд Node:

index.js


// ... 其他代码省略,请自行前往章节 4.2 后端接口 获取其他代码

if (pathName == "/sendMessage") { // 提交留言信息

  console.log("\n【API - 提交留言信息】");

  result = JSON.parse(result);

  let id = result.userid; // id
  let userName = result.username; // 用户名
  let messageText = result.message; // 留言内容
  let time = getNowFormatDate(); // 时间

  if(!messageText) {
    res.end("登录失败,留言内容为空!");
    return;
  } else if(messageText.length > 140) {
    res.end("登录失败,字数超过限制!");
    return;
  } else {
    
    // 新增的 SQL 语句及新增的字段信息
    let addSql = "INSERT INTO message(user_message, user_id, user_name, time) VALUES(?, ?, ?, ?)";
    let addSqlParams = [messageText, id, userName, time];

    // 连接 SQL 并实施语句
    connection.query(addSql, addSqlParams, function (error1, response1) {
      if (error1) { // 如果 SQL 语句错误
        throw error1;
      } else {
        console.log("\n新增成功!");

        // 返回数据
        res.write(JSON.stringify({
          code: "0",
          message: "新增成功!"
        }));

        // 结束响应
        res.end();
      }
    })
  }

} else if (pathName == "/login") { // 登录

  console.log("\n【API - 登录】");

} else if (pathName == "/register") { // 注册

  console.log("\n【API - 注册】");

}



// ... 其他代码省略,请自行前往章节 4.2 后端接口 获取其他代码



if (pathName == "/getMessage") { // 获取留言信息

  console.log("\n【API - 获取留言信息】");

  // 解析 url 参数部分
  let params = url.parse(req.url, true).query;

  console.log("\n参数为:");
  console.log(params);

  // 新增的 SQL 语句及新增的字段信息
  let readSql = "SELECT * FROM message";

  // 连接 SQL 并实施语句
  connection.query(readSql, function (error1, response1) {
    if (error1) {
      throw error1; 
    } else {
      
      let newRes = JSON.parse(JSON.stringify(response1));
      console.log(newRes);

      // 返回数据
      res.write(JSON.stringify({
        code: "1",
        message: "查询成功!",
        data: newRes
      }));

      // 结束响应
      res.end();
    }
  });
  // 查询完毕
} else if(pathName == "/") { // 首页
  res.writeHead(200, {
    "Content-Type": "text/html;charset=UTF-8"
  });

  res.write('<h1 style="text-align:center">jsliang 前端有限公司服务已开启!</h1><h2 style="text-align:center">详情可见:<a href="https://github.com/LiangJunrong/document-library/blob/master/other-library/Node/NodeBase.md" target="_blank">Node 基础</a></h2>');

  res.end();
}

  Закончите вводить код и посмотрите, реализована ли функция:

 Подводя итог, мы завершили все функциональные модули: регистрация, вход и сообщение.

Интеграция с пятью инструментами

Назад к содержанию

Если рабочий хочет хорошо работать, он должен сначала заточить свои инструменты.
 Имея под рукой инструменты, вы сможете быстрее развиваться.

5.1 супервизор — отслеживание изменений узла

Назад к содержанию

  Как говорится на официальном сайте, это система управления:

  1. Установите плагин:npm i supervisor -g
  2. Запустите файл:supervisor app.js
  3. Проверьте это:localhost:3000

 Обычно мыnode app.jsПосле этого, когда мы изменилиapp.js, вам нужно закрыть командную строку узла перед выполнениемnode app.js.
  И мы используемsupervisorПосле этого мы модифицировалиapp.jsПока вы нажимаете «Сохранить», сохраненный код вступает в силу, что позволяет отслеживать изменения кода узла в режиме реального времени.

  Более подробные онлайн-руководства по этому инструменту:

5.2 PM2 — Управление процессами узла

Назад к содержанию

 PM2 — это инструмент управления процессами Node, который можно использовать для упрощения многих утомительных задач управления приложениями Node, таких как мониторинг производительности, автоматический перезапуск, балансировка нагрузки и т. д., и он очень прост в использовании.

 Далее представлено вводное введение в PM2, которое в основном охватывает общие функции и конфигурации PM2:

  1. Установите PM2 глобально:npm i pm2 -g
  2. Приложение для мониторинга:pm2 start index.js
  3. Посмотреть все процессы:pm2 list
  4. Просмотр процесса:pm2 describe App name/id
  5. Остановить процесс:pm2 stop App name/id. Например:

пройти первымpm2 listПроверить:

App name id status
index 0 online

  Просто выполнитьpm2 stop indexилиpm2 stop 0Вот и все.

  1. Остановить все процессы:pm2 stop all
  2. Перезапустите процесс:pm2 restart App name/id
  3. Удалить процесс:pm2 delete App name/id

  Как и выше, если нашsupervisorЕсли он отслеживает один процесс, тоPM2заключается в мониторинге нескольких процессов.

 Больше рейдеров:

6 ссылок

Назад к содержанию

  В процессе написания этой статьи есть несколько ссылок, которые стоит прочитать:

  1. Классика: Эту категорию стоит изучить

Классика, то есть с течением времени она все так же ценна.

  1. Попробуйте: этот класс достоин нашей ссылки

Базовый модуль узла

Интерфейс записи узла

обучение MySQL

Узел подключается к базе данных

Узел имитирует Express

Семь онлайн-развертываний

Назад к содержанию

 Об онлайн-развертывании и настройке, связанных с доменным именем и сервером,jsliangОбъяснение в другой статье:Построение облачного сервера.

 Если небольшому партнеру необходимо заказать облачный сервер для хранения статических или поддерживаемых узлом веб-страниц, таких как личный веб-сайт jsliang, но он не знает, как выбрать, вы можете добавитьjsliangQQ:1741020489Для консультаций вот некоторые акции:

Облачная акция Tencent:

 Новые пользователи нажмите здесь:

 Купить облачный сервер:


Облачное продвижение Alibaba:

 Новые пользователи нажмите здесь:

 Купить облачный сервер:

 Купить облачный сервер корпоративного уровня:

Восемь резюме

Назад к содержанию

 Подводя итог, сделай все!
 Возможно, из-за разрухи предыдущего кодекса здесь очень мало друзей, но я твердо верю, что в основном объяснил то, что должен объяснять, и объясню, чего не должен~
  Итак, если вашим друзьям действительно стало хорошо после прочтения, то поставьте лайк или звездочку! Ваши лайки и звезды - моя мотивация писать все больше и больше интересных статей!Адрес GitHub

 Если вы хотите оставить комментарий после прочтения этого, вы можете добавить код:Node 基础,***,такjsliangЯ вернусь, когда увижу это, ха-ха~

  • Основы Node, я готов!
  • Основы Node, я хочу сказать, что jsliang должен быть ленивым и написан не самым совершенным, мне все равно, если я вознагражу вас, поторопитесь и улучшите его для меня!
  • ...

so, that's all, thanks~

-----------------------

постскриптум

Написать статью нелегко. Если статья будет полезна моим друзьям, я надеюсь, что мои друзья дадут вознаграждение WeChat/Alipay jsliang, который усердно работает над кодированием и написанием статей. Каждая награда — лучшее поощрение, спасибо~

知识共享许可协议
jsliangбиблиотека документацииЗависит отЛян ЦзюньронгиспользоватьCreative Commons Attribution-NonCommercial-ShareAlike 4.0 Международная лицензияЛицензия.
на основеGitHub.OM/l ЯнДжун Рон…Создание работ выше.
Права на использование, отличные от разрешенных в настоящем Лицензионном соглашении, могут быть получены отCreative Commons.org/licenses/не…получено в.