前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Node.js 极简教程》 东海陈光剑

《Node.js 极简教程》 东海陈光剑

作者头像
一个会写诗的程序员
发布2019-02-22 15:08:51
1.5K0
发布2019-02-22 15:08:51
举报

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。 https://nodejs.org

快速开始 Hello World

Node 是什么

  • 简史
    • 是什么
      • Node.js是一个Javascript运行环境(runtime environment),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js 不是一个 JavaScript 框架,不同于CakePHP、Django、Rails。Node.js 更不是浏览器端的库,不能与 jQuery、ExtJS 相提并论。Node.js 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。
    • 发展史
      • 2009年2月,Ryan Dahl在博客上宣布准备基于V8创建一个轻量级的Web服务器并提供一套库。
      • 2009年5月,Ryan Dahl在GitHub上发布了最初版本的部分Node.js包,随后几个月里,有人开始使用Node.js开发应用。
      • 2009年11月和2010年4月,两届JSConf大会都安排了Node.js的讲座。
      • 2010年年底,Node.js获得云计算服务商Joyent资助,创始人Ryan Dahl加入Joyent全职负责Node.js的发展。
      • 2011年7月,Node.js在微软的支持下发布Windows版本。
  • 特征
    • 非阻塞I/O(单线程、非阻塞)&事件轮询【Single Threaded Event Loop】
      • Node通过事件驱动的方式处理请求时无需为每一个请求创建额外的线程。在事件驱动的模型当中,每一个IO工作被添加到事件队列中,线程循环地处理队列上的工作任务,当执行过程中遇到来堵塞(读取文件、查询数据库)时,线程不会停下来等待结果,而是留下一个处理结果的回调函数,转而继续执行队列中的下一个任务。这个传递到队列中的回调函数在堵塞任务运行结束后才被线程调用。
    • 优点
      • 高并发(最重要的优点)
      • 适合I/O密集型应用
      • RESTful API
      • npm,前后端分离
    • 缺陷
      • 回调模式下的异步是有明显缺陷的,程序的执行顺序必须依靠回调来保证,没有层层回调,就没有可以保障的逻辑顺序,这也就注定了,node不能做复杂的业务逻辑。
      • 回调山真不是必须的。
      • 不适合CPU密集型应用
      • 只支持单核CPU,不能充分利用CPU
      • 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃,原因:单进程,单线程。
      • Debug不方便,错误没有stack trace
  • nodejs中的库方法是异步的,异步方法是约定。

环境配置

Hello World 示例

Once you have installed Node, let's try building our first web server. Create a file named "app.js", and paste the following code:

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

After that, run your web server using node app.js, visit http://localhost:3000, and you will see a message 'Hello World'

NPM 使用介绍

  • npm 简介
    • NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:

允许用户从NPM服务器下载别人编写的第三方包到本地使用。 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。 由于新版的nodejs已经集成了npm,所以之前npm也一并安装好了。同样可以通过输入 "npm -v" 来测试是否成功安装。命令如下,出现版本提示表示安装成功:

$ npm -v
6.4.1

如果你安装的是旧版本的 npm,可以很容易得通过 npm 命令来升级,命令如下:

$ sudo npm install npm -g

Node 架构与运行原理

Node 架构分析

  • 架构图
  • nodejs组成部分
    • v8 engine
      • 虚拟机的功能,执行js代码
      • 提供C++函数接口,为nodejs提供v8初始化,创建context,scope等
    • libuv
      • 基于事件驱动的异步IO模型库,我们的js代码发出请求,最终由libuv完成,而我们所设置的回调函数则是在libuv触发
    • builtin modules
      • 由C++代码写成各类模块,包含了crypto,zlib, file stream etc 基础功能。(v8提供了函数接口,libuv提供异步IO模型库,以及一些nodejs函数,为builtin modules提供服务)
    • native modules
      • 由js写成,提供我们应用程序调用的库,同时这些模块又依赖builtin modules来获取相应的服务支持
    • 建立http server为例
      • http server 建立过程

ES6 features

Node.js ES2015 Support

Node 模块系统

简介

创建模块

加载模块

Node 全局对象

是什么

  • JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。
  • 在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。
  • 在 Node.js 我们可以直接访问到 global 的属性,而不需要在应用中包含它。

文件操作

简介

  • Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示:
  • var fs = require("fs")

异步和同步

  • Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
  • 异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
  • 建议大家使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。
  • 阻塞代码实例
    • 创建一个文件 input.txt ,内容如下:
Node.js 极简教程

创建 main.js 文件, 代码如下:

var fs = require("fs");

var data = fs.readFileSync('input.txt');

console.log(data.toString());
console.log("程序执行结束!");

以上代码执行结果如下:

$ node main.js

Node.js 极简教程
程序执行结束!
  • 非阻塞代码实例
    • 创建一个文件 input.txt ,内容如下:
Node.js 极简教程

创建 main.js 文件, 代码如下:

var fs = require("fs");

fs.readFile('input.txt', function (err, data) {
    if (err) return console.error(err);
    console.log(data.toString());
});

console.log("程序执行结束!");

以上代码执行结果如下:

$ node main.js
程序执行结束!
Node.js 极简教程

以上两个实例我们了解了阻塞与非阻塞调用的不同。第一个实例在文件读取完后才执行完程序。 第二个实例我们不需要等待文件读取完,这样就可以在读取文件时同时执行接下来的代码,大大提高了程序的性能。

因此,阻塞是按顺序执行的,而非阻塞是不需要按顺序的,所以如果需要处理回调函数的参数,我们就需要写在回调函数内。

Web 模块

Web 服务器简介

  • Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,Web服务器的基本功能就是提供Web信息浏览服务。它只需支持HTTP协议、HTML文档格式及URL,与客户端的网络浏览器配合。

大多数 web 服务器都支持服务端的脚本语言(php、python、ruby)等,并通过脚本语言从数据库获取数据,将结果返回给客户端浏览器。

目前最主流的三个Web服务器是Apache、Nginx、IIS。

使用 Node 创建 Web 服务器

  • Node.js 提供了 http 模块,http 模块主要用于搭建 HTTP 服务端和客户端,使用 HTTP 服务器或客户端功能必须调用 http 模块,代码如下:
var http = require('http');

以下是演示一个最基本的 HTTP 服务器架构(使用 8080 端口),创建 index.js 文件,代码如下所示:

实例

var http = require('http');
var fs = require('fs');
var url = require('url');
 
 
// 创建服务器
http.createServer( function (request, response) {  
   // 解析请求,包括文件名
   var pathname = url.parse(request.url).pathname;
   
   // 输出请求的文件名
   console.log("Request for " + pathname + " received.");
   
   // 从文件系统中读取请求的文件内容
   fs.readFile(pathname.substr(1), function (err, data) {
      if (err) {
         console.log(err);
         // HTTP 状态码: 404 : NOT FOUND
         // Content Type: text/plain
         response.writeHead(404, {'Content-Type': 'text/html'});
      }else{             
         // HTTP 状态码: 200 : OK
         // Content Type: text/plain
         response.writeHead(200, {'Content-Type': 'text/html'});    
         
         // 响应文件内容
         response.write(data.toString());        
      }
      //  发送响应数据
      response.end();
   });   
}).listen(8080);
 
// 控制台会输出以下信息
console.log('Server running at http://127.0.0.1:8080/');

接下来我们在该目录下创建一个 index.html 文件,代码如下:

index.html 文件

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Node.js 极简教程</title>
</head>
<body>
    <h1>我的第一个标题</h1>
    <p>我的第一个段落。</p>
</body>
</html>

执行 index.js 文件:

$ node index.js
Server running at http://127.0.0.1:8080/
Request for / received.
{ [Error: ENOENT: no such file or directory, open ''] errno: -2, code: 'ENOENT', syscall: 'open', path: '' }
Request for /index.html received.
Request for /favicon.ico received.
{ [Error: ENOENT: no such file or directory, open 'favicon.ico']
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'favicon.ico' }
Request for /index.html received.
Request for /favicon.ico received.
{ [Error: ENOENT: no such file or directory, open 'favicon.ico']
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'favicon.ico' }

直接访问 http://127.0.0.1:8080/, 提示 HTTP ERROR 404 Not found:

因为,我们代码里没有对根路径进行映射处理。

接着我们在浏览器中打开地址:http://127.0.0.1:8080/index.html,显示如下图所示:

MySQL数据库操作

安装驱动

$ cnpm install mysql

连接数据库

  • 在以下实例中根据你的实际配置修改数据库用户名、及密码及数据库名:

test.js 文件代码:

var mysql      = require('mysql');
var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '123456',
  database : 'test'
});
 
connection.connect();
 
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
  if (error) throw error;
  console.log('The solution is: ', results[0].solution);
});

执行以下命令输出结果为:

$ node test.js
The solution is: 2

数据库 CRUD 操作

  • 查询数据
    • 查询数据
var mysql  = require('mysql');  
 
var connection = mysql.createConnection({     
  host     : 'localhost',       
  user     : 'root',              
  password : '123456',       
  port: '3306',                   
  database: 'test', 
}); 
 
connection.connect();
 
var  sql = 'SELECT * FROM websites';
//查
connection.query(sql,function (err, result) {
        if(err){
          console.log('[SELECT ERROR] - ',err.message);
          return;
        }
 
       console.log('--------------------------SELECT----------------------------');
       console.log(result);
       console.log('------------------------------------------------------------\n\n');  
});
 
connection.end();
  • 插入数据
    • 插入数据
var mysql  = require('mysql');  
 
var connection = mysql.createConnection({     
  host     : 'localhost',       
  user     : 'root',              
  password : '123456',       
  port: '3306',                   
  database: 'test', 
}); 
 
connection.connect();
 
var  addSql = 'INSERT INTO websites(Id,name,url,alexa,country) VALUES(0,?,?,?,?)';
var  addSqlParams = ['菜鸟工具', 'https://c.runoob.com','23453', 'CN'];
//增
connection.query(addSql,addSqlParams,function (err, result) {
        if(err){
         console.log('[INSERT ERROR] - ',err.message);
         return;
        }        
 
       console.log('--------------------------INSERT----------------------------');
       //console.log('INSERT ID:',result.insertId);        
       console.log('INSERT ID:',result);        
       console.log('-----------------------------------------------------------------\n\n');  
});
 
connection.end();

执行以下命令输出就结果为:

$ node test.js
--------------------------INSERT----------------------------
INSERT ID: OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 6,
  serverStatus: 2,
  warningCount: 0,
  message: '',
  protocol41: true,
  changedRows: 0 }
-----------------------------------------------------------------
  • 更新数据
    • 我们也可以对数据库的数据进行修改:

更新数据

var mysql  = require('mysql');  
 
var connection = mysql.createConnection({     
  host     : 'localhost',       
  user     : 'root',              
  password : '123456',       
  port: '3306',                   
  database: 'test', 
}); 
 
connection.connect();
 
var modSql = 'UPDATE websites SET name = ?,url = ? WHERE Id = ?';
var modSqlParams = ['菜鸟移动站', 'https://m.runoob.com',6];
//改
connection.query(modSql,modSqlParams,function (err, result) {
   if(err){
         console.log('[UPDATE ERROR] - ',err.message);
         return;
   }        
  console.log('--------------------------UPDATE----------------------------');
  console.log('UPDATE affectedRows',result.affectedRows);
  console.log('-----------------------------------------------------------------\n\n');
});
 
connection.end();

执行以下命令输出就结果为:

--------------------------UPDATE----------------------------
UPDATE affectedRows 1
-----------------------------------------------------------------
  • 删除数据
    • 我们可以使用以下代码来删除 id 为 6 的数据:

删除数据

var mysql  = require('mysql');  
 
var connection = mysql.createConnection({     
  host     : 'localhost',       
  user     : 'root',              
  password : '123456',       
  port: '3306',                   
  database: 'test', 
}); 
 
connection.connect();
 
var delSql = 'DELETE FROM websites where id=6';
//删
connection.query(delSql,function (err, result) {
        if(err){
          console.log('[DELETE ERROR] - ',err.message);
          return;
        }        
 
       console.log('--------------------------DELETE----------------------------');
       console.log('DELETE affectedRows',result.affectedRows);
       console.log('-----------------------------------------------------------------\n\n');  
});
 
connection.end();

执行以下命令输出就结果为:

--------------------------DELETE----------------------------
DELETE affectedRows 1
-----------------------------------------------------------------

Kotlin 开发者社区

国内第一Kotlin 开发者社区公众号,主要分享、交流 Kotlin 编程语言、Spring Boot、Android、React.js/Node.js、函数式编程、编程思想等相关主题。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.11.05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 快速开始 Hello World
    • Node 是什么
      • 环境配置
        • Hello World 示例
          • NPM 使用介绍
          • Node 架构与运行原理
            • Node 架构分析
            • ES6 features
              • Node.js ES2015 Support
              • Node 模块系统
                • 简介
                  • 创建模块
                    • 加载模块
                    • Node 全局对象
                      • 是什么
                      • 文件操作
                        • 简介
                          • 异步和同步
                          • Web 模块
                            • Web 服务器简介
                              • 使用 Node 创建 Web 服务器
                              • MySQL数据库操作
                                • 安装驱动
                                  • 连接数据库
                                    • 数据库 CRUD 操作
                                    • Kotlin 开发者社区
                                    相关产品与服务
                                    云数据库 MySQL
                                    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档