如何正确学习Node

0 :Node.js简介

如今,愈来愈多的科技公司和开发者开始使用 Node.js 开发各类应用。Node.js除了可以辅助大前端开发外,还能够编写Web应用,封装Api,组装RPC服务等,甚至是开发VSCode编辑器同样的PC客户端。和其它技术相比, Node.js 简单易学,性能好、部署容易,可以轻松处理高并发场景下的大量服务器请求。Node.js 周边的生态也很是强大,NPM(Node包管理)上有超过60万个模块,日下超过载量3亿次。但编写 Node.js 代码对新人和其它语言背景的开发者来讲,不是一件容易的事,在入门以前须要弄懂很多复杂的概念。前端

a)Node.js简介vue

  • 优势: Node.js 不是一门语言也不是框架,它只是基于 Google V8 引擎的 JavaScript 运行时环境,同时结合 Libuv 扩展了 JavaScript 功能,使之支持 io、fs 等只有语言才有的特性,使得 JavaScript 可以同时具备 DOM 操做(浏览器)和 I/O、文件读写、操做数据库(服务器端)等能力,是目前最简单的全栈式语言。

早在2007年,Jeff Atwood 就提出了著名的 Atwood定律java

任何可以用 JavaScript 实现的应用系统,最终都必将用 JavaScript 实现node

  • 缺点:

固然了,Node.js 也有一些缺点。Node.js 常常被人们吐槽的一点就是:回调太多难于控制(俗称回调地狱)和 CPU 密集任务处理的不是很好。可是,目前异步流程技术已经取得了很是不错的进步,从Callback、Promise 到 Async函数,能够轻松的知足全部开发需求。至于 CPU 密集任务处理并不是不可解,方案有不少,好比经过系统底层语言 Rust 来扩展 Node.js,但这样会比较麻烦。笔者坚信在合适的场景使用合适的东西,尤为是在微服务架构下,一切都是服务,能够作到语言无关。若是你们想使 JavaScript 作 CPU 密集任务,推荐 Node.js 的兄弟项目 fibjs,基于纤程(fiber,能够简单理解为更轻量级的线程),效率很是高,兼容npm,同时没有异步回调烦恼。 b)什么是Node.js?mysql

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.react

  • Node.js 不是 JavaScript 应用,不是语言(JavaScript 是语言),不是像 Rails(Ruby)、 Laravel(PHP) 或 Django(Python) 同样的框架,也不是像 Nginx 同样的 Web 服务器。Node.js 是 JavaScript 运行时环境
  • 构建在 Chrome's V8 这个著名的 JavaScript 引擎之上,Chrome V8 引擎以 C/C++ 为主,至关于使用JavaScript 写法,转成 C/C++ 调用,大大的下降了学习成本
  • 事件驱动(event-driven),非阻塞 I/O 模型(non-blocking I/O model),简单点讲就是每一个函数都是异步的,最后由 Libuv 这个 C/C++ 编写的事件循环处理库来处理这些 I/O 操做,隐藏了非阻塞 I/O 的具体细节,简化并发编程模型,让你能够轻松的编写高性能的Web应用,因此它是轻量(lightweight)且高效(efficient)的
  • 使用 npm 做为包管理器,目前 npm 是开源库里包管理最大的生态,功能强大,截止到2017年12月,模块数量超过 60 万+
  • 应用: 大多数人都认为 Node.js 只能写网站后台或者前端工具,这实际上是不全面的,Node.js的目标是让并发编程更简单,主要应用在以网络编程为主的 I/O 密集型应用。它是开源的,跨平台,而且高效(尤为是I/O处理),包括IBM、Microsoft、Yahoo、SAP、PayPal、沃尔玛及GoDaddy都是 Node.js 的用户。

c)基本原理jquery

下面是一张 Node.js 早期的架构图,来自 Node.js 之父 Ryan Dahl 的演讲稿,在今天依然不过期,它简要的介绍了 Node.js 是基于 Chrome V8引擎构建的,由事件循环(Event Loop)分发 I/O 任务,最终工做线程(Work Thread)将任务丢到线程池(Thread Pool)里去执行,而事件循环只要等待执行结果就能够了。 git

核心概念程序员

  • Chrome V8 是 Google 发布的开源 JavaScript 引擎,采用 C/C++ 编写,在 Google 的 Chrome 浏览器中被使用。Chrome V8 引擎能够独立运行,也能够用来嵌入到 C/C++ 应用程序中执行。
  • Event Loop 事件循环(由 libuv 提供)
  • Thread Pool 线程池(由 libuv 提供)

梳理一下es6

  • Chrome V8 是 JavaScript 引擎
  • Node.js 内置 Chrome V8 引擎,因此它使用的 JavaScript 语法
  • JavaScript 语言的一大特色就是单线程,也就是说,同一个时间只能作一件事
  • 单线程就意味着,全部任务须要排队,前一个任务结束,才会执行后一个任务。若是前一个任务耗时很长,后一个任务就不得不一直等着。
  • 若是排队是由于计算量大,CPU 忙不过来,倒也算了,可是不少时候 CPU 是闲着的,由于 I/O 很慢,不得不等着结果出来,再往下执行
  • CPU 彻底能够无论 I/O 设备,挂起处于等待中的任务,先运行排在后面的任务
  • 将等待中的 I/O 任务放到 Event Loop 里
  • 由 Event Loop 将 I/O 任务放到线程池里
  • 只要有资源,就尽力执行
  • Chrome V8 解释并执行 JavaScript 代码(这就是为何浏览器能执行 JavaScript 缘由)
  • libuv 由事件循环和线程池组成,负责全部 I/O 任务的分发与执行

1. 前言:学习 Node.js 的三个境界

  • 打日志:console.log
  • 断点调试:断点调试:node debugger 或node inspector 或vscode
  • 测试驱动开发(tdd | bdd)

2. 准备与学习:

基础学习

1)js语法必须会

  1. js基本语法,都是c语系的,有其余语言背景学习起来相对更简单
  2. 常见用法,好比正则,好比数据结构,尤为是数组的几种用法。好比bind/call/apply等等
  3. 面向对象写法。js是基于对象的,因此它的oo写起来很是诡异。参见红皮书JavaScript高级编程,不少框架都是本身实现oo基础框架,好比ext-core等。

2)我的学习和技术选型都要按部就班

  1. 先能写,采用面向过程写法,简单理解就是定义一堆function,而后调用,很是简单
  2. 而后再追求更好的写法,能够面向对象。对于规模化的编程来讲,oo是有它的优点的,通常java、c#,ruby这些语言里都有面向对象,因此后端更习惯,但对于语言经验不那么强的前端来讲算高级技巧。
  3. 等oo玩腻了,能够有更好的追求:函数式编程,不管编程思惟,仍是用法上都对已有的编程思惟是个挑战。我很喜欢函数式,但不太会在团队里使用,毕竟oo阶段还没彻底掌握,风险会比较大。但若是团队水平都很是高了,团队稳定是能够用的。

能够看出个人思路,先能写,而后再追求更好的写法,好比面向对象。等团队水平到必定程度了,而且稳定的时候,能够考虑更加极致的函数式写法。

3)各类高级的JavaScript友好语言

JavaScript友好语言指的是可以使用其余语法实现,但最终编译成js的语言。自从Node.js出现后,这种黑科技层出不穷。好比比较有名的coffee、typescript、babel(es)等。

CoffeeScript虽然也是JavaScript友好语言,但其语法借鉴ruby,崇尚极简,对于类型和OO机制上仍是偏弱,并且这么多年也没发展起来,仍然是比较小众的活着。将来比例会愈来愈少的。

显然TypeScript会愈来愈好,TypeScript 的强大之处是要用过才知道的。

  • 1)规模化编程,像Java那种,静态类型,面向对象,前端只有TypeScript能作到
  • 2)亲爹是微软安德斯·海尔斯伯格,不知道此人的请看borland传奇去
  • 3)开源,将来很好
  • 4)组合拳:TypeScript + VSCode = 神器

当下前端发展速度极快,以指数级的曲线增加。之前可能1年都不必定有一项新技术,如今可能每月都有。大前端,Node全栈,架构演进等等都在快速变化。能够说,前端越复杂,有越多的不肯定性,TypeScript的机会就越大。 4)再论面向对象

面向对象想用好也不容易的,并且js里有各类实现,真是让人眼花缭乱。

  • 基于原型的写法,纵观JavaScript高级编程,就是翻来覆去的讲这个,这个很基础,但很差是很好用。能够不用,但不能够不会。
  • 本身写面向对象机制是最好的,但不是每一个人都有这个能力的。好在es6规范出了更好一点的面向对象,经过class、extends、super关键字来定义类,已经明显好不少了,虽然还很弱,但起码勉强能用起来了。从面向过程走过来的同窗,推荐这种写法,简单易用。但要注意面向对象要有面向对象的写法,要理解抽象,继承,封装,多态4个基本特征。若是想用好,你甚至还须要看一些设计模式相关的书。好在有《JavaScript设计模式》一书。Koa2里已经在用这种写法了。
  • js是脚本语言,解释便可执行。因此它的最大缺点是没有类型系统,这在规模化编程里是很是危险的,一个函数,传参就能玩死人。因而如今流行使用flow和typescript来作类型校验。flow只是工具,比较轻量级。而typescript是es6超级,给es6补充了类型系统和更完善的面向对象机制,因此大部分人都会对ts有好感,颇有多是将来的趋势。

Node.js应用场景

《Node.js in action》一书里说,Node.js 所针对的应用程序有一个专门的简称:DIRT。它表示数据密集型实时(data-intensive real-time)程序。由于 Node.js 自身在 I/O 上很是轻量,它善于将数据从一个管道混排或代理到另外一个管道上,这能在处理大量请求时持有不少开放的链接,而且只占用一小部份内存。它的设计目标是保证响应能力,跟浏览器同样。

这话不假,但在今天来看,DIRT 仍是范围小了。其实 DIRT 本质上说的 I/O 处理的都算,但随着大前端的发展,Node.js 已经再也不只是 I/O 处理相关,而是更加的“Node”!

  • 1)跨平台:覆盖你能想到的面向用户的全部平台,传统的PC Web端,以及PC客户端 nw.js/electron 、移动端 cordova、HTML五、react-nativeweex,硬件 ruff.io
  • 2)Web应用开发:网站、Api、RPC服务等
  • 3)前端:三大框架 React \ Vue \ Angular 辅助开发,以及工程化演进过程(使用Gulp /Webpack 构建 Web 开发工具)
  • 4)工具:npm上各类工具模块,包括各类前端预编译、构建工具 Grunt / Gulp、脚手架,命令行工具,各类奇技淫巧等

Node.js 应用场景很是丰富,好比 Node.js 能够开发操做系统,但通常我都不讲的,就算说了也没多大意义,难道你们真的会用吗?通常,我习惯将 Node.js 应用场景氛围7个部分。

1)初衷,server端,不想成了前端开发的基础设施 2)命令行辅助工具,甚至能够是运维 3)移动端:cordova,pc端:nw.js和electron 4)组件化,构建,代理 5)架构,先后端分离、api proxy 6)性能优化、反爬虫与爬虫 7) 全栈最便捷之路

Node核心:异步流程控制

Node.js是为异步而生的,它本身把复杂的事儿作了(高并发,低延时),交给用户的只是有点难用的Callback写法。也正是坦诚的将异步回调暴露出来,才有更好的流程控制方面的演进。也正是这些演进,让Node.js从DIRT(数据敏感实时应用)扩展到更多的应用场景,今天的Node.js已经不仅是能写后端的JavaScript,已经涵盖了全部涉及到开发的各个方面,而Node全栈更是热门种的热门。

直面问题才能有更好的解决方式,Node.js的异步是整个学习Node.js过程当中重中之重。

    1. 异步流程控制学习重点
  • 2)Api写法:Error-first Callback 和 EventEmitter
  • 3)中流砥柱:Promise
  • 4)终极解决方案:Async/Await
  1. 异步流程控制学习重点

我整理了一张图,更直观一些。从09年到如今,8年多的时间里,整个Node.js社区作了大量尝试,其中曲折足足够写一本书的了。你们先简单了解一下。

  • 红色表明Promise,是使用最多的,不管async仍是generator均可用
  • 蓝色是Generator,过分货
  • 绿色是Async函数,趋势

结论:Promise是必须会的,那你为何不顺势而为呢?

推荐:使用Async函数 + Promise组合,以下图所示。

结论

  1. Node.js SDK里callback写法必须会的。
  2. Node.js学习重点: Async函数与Promise
    1. 中流砥柱:Promise
    2. 终极解决方案:Async/Await

2)Api写法:Error-first Callback 和 EventEmitter a)Error-first Callback 定义错误优先的回调写法只须要注意2条规则便可:

  • 回调函数的第一个参数返回的error对象,若是error发生了,它会做为第一个err参数返回,若是没有,通常作法是返回null。
  • 回调函数的第二个参数返回的是任何成功响应的结果数据。若是结果正常,没有error发生,err会被设置为null,并在第二个参数就出返回成功结果数据。

下面让咱们看一下调用函数示例,Node.js 文档里最常采用下面这样的回调方式:

function(err, res) {
  // process the error and result
}
复制代码

这里的 callback 指的是带有2个参数的函数:"err"和 "res"。语义上讲,非空的“err”至关于程序异常;而空的“err”至关于能够正常返回结果“res”,无任何异常。 b)EventEmitter

事件模块是 Node.js 内置的对观察者模式“发布/订阅”(publish/subscribe)的实现,经过EventEmitter属性,提供了一个构造函数。该构造函数的实例具备 on 方法,能够用来监听指定事件,并触发回调函数。任意对象均可以发布指定事件,被 EventEmitter 实例的 on 方法监听到。

在node 6以后,能够直接使用require('events')

var EventEmitter = require('events')
var util = require('util')

var MyEmitter = function () {
 
}
util.inherits(MyEmitter, EventEmitter)

const myEmitter = new MyEmitter();

myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
    // Prints: a b {}
});

myEmitter.emit('event', 'a', 'b');
复制代码

和jquery、vue里的Event是很是相似的。并且前端本身也有EventEmitter。 c)如何更好的查Node.js文档

API是应用程序接口Application Programming Interface的简称。从Node.js异步原理,咱们能够知道,核心在于 Node.js SDK 中API调用,而后交由EventLoop(Libuv)去执行,因此咱们必定要熟悉Node.js的API操做。

Node.js的API都是异步的,同步的函数是奢求,要查API文档,在高并发场景下慎用。

笔者推荐使用 DashZeal 查看离线文档,常常查看离线文档,对Api理解会深刻不少,比IDE辅助要好,能够有效避免离开IDE就不会写代码的窘境。 3)中流砥柱:Promise 回调地狱

Node.js 由于采用了错误优先的回调风格写法,致使sdk里导出都是回调函数。若是组合调用的话,就会特别痛苦,常常会出现回调里嵌套回调的问题,你们都很是厌烦这种写法,称之为Callback Hell,即回调地狱。一个经典的例子来自著名的Promise模块q文档里。

step1(function (value1) {
    step2(value1, function(value2) {
        step3(value2, function(value3) {
            step4(value3, function(value4) {
                // Do something with value4
            });
        });
    });
});
复制代码

这里只是作4步,嵌套了4层回调,若是更多步骤呢?不少新手浅尝辄止,到这儿就望而却步,粉转黑。这明显不够成熟,最起码你要看看它的应对解决方案吧! Node.js 约定全部Api都采用错误优先的回调方式,这部分场景都是你们直接调用接口,无太多变化。而Promise是对回调地狱的思考,或者说是改良方案。目前使用很是广泛,能够说是在async函数普及以前惟一一个通用性规范,甚至 Node.js 社区都在考虑 Promise 化,可见其影响之大。

Promise最先也是在commonjs社区提出来的,当时提出了不少规范。比较接受的是promise/A规范。后来人们在这个基础上,提出了promise/A+规范,也就是实际上如今的业内推行的规范。ES6 也是采用的这种规范。 Promise意味着[许愿|承诺]一个尚未完成的操做,但在将来会完成的。与Promise最主要的交互方法是经过将函数传入它的then方法从而获取得Promise最终的值或Promise最终最拒绝(reject)的缘由。要点有三个:

  • 递归,每一个异步操做返回的都是promise对象

  • 状态机:三种状态转换,只在promise对象内部能够控制,外部不能改变状态

  • 全局异常处理 Async函数要点以下:

  • Async函数语义上很是好

  • Async不须要执行器,它自己具有执行能力,不像Generator须要co模块

  • Async函数的异常处理采用try/catch和Promise的错误处理,很是强大

  • Await接Promise,Promise自身就足够应对全部流程了,包括async函数没有纯并行处理机制,也能够采用Promise里的all和race来补齐

  • Await释放Promise的组合能力,外加co和Promise的then,几乎没有不支持的场景

综上所述

  • Async函数是趋势,若是Chrome 52. v8 5.1已经支持Async函数(https://github.com/nodejs/CTC/issues/7)了,Node.js支持还会远么?
  • Async和Generator函数里都支持promise,因此promise是必须会的。
  • Generator和yield异常强大,不过不会成为主流,因此学会基本用法和promise就行了,不必全部的都必须会。
  • co做为Generator执行器是不错的,它更好的是当作Promise 包装器,经过Generator支持yieldable,最后返回Promise,是否是有点无耻?
    1. 异步流程控制学习重点
  • 2)Api写法:Error-first Callback 和 EventEmitter
  • 3)中流砥柱:Promise
  • 4)终极解决方案:Async/Await

Web编程要点

通常,后端开发指的是 Web 应用开发中和视图渲染无关的部分,主要是和数据库交互为主的重业务型逻辑处理。但如今架构升级后,Node.js 承担了先后端分离重任以后,有了更多玩法。从带视图的传统Web应用面向Api接口应用,到经过 RPC 调用封装对数据库的操做,到提供前端 Api 代理和网关,服务组装等,统称为后端开发,再也不是以往只有和数据库打交道的部分才算后端。这样,就可让前端工程师对开发过程可控,更好的进行调优和性能优化。 对 Node.js 来讲,一直没有在后端取得其合理的占有率,缘由是多方面的,暂列几条。

  • 1)利益分配,已有实现大可能是Java或者其余语言,基本是无法撼动的,重写的成本是巨大的,另外,若是用Node写了,那么那些写Java的人怎么办?抢人饭碗,这是要拼命的。
  • 2)Node相对年轻,你们对Node的理解不够,回调和异步流程控制略麻烦,不少架构师都不肯意花时间去学习。尽管在Web应用部分处理起来很是简单高效,但在遇到问题时并不容易排查定位,对开发者水平要求略高。
  • 3)开发者技能单一,不少是从前端转过来的,对数据库,架构方面知识欠缺,对系统设计也知之很少,这是很危险的,有种麻杆打狼两头惧怕的感受。
  • 4)Node在科普、培训、布道等方面作的并很差,国外使用的很是多,国内却不多人知道,不如某些语言作得好。

尽管如此,Node.js 仍是尽人皆知,卷入各类是非风口,也算是在大前端浪潮中大红大紫。缘由它的定位很是明确,补足以 JavaScript 为核心的全栈体系中服务器部分。开发也是人,可以同时掌握并精通多门语言的人毕竟很少,并且程序员的美德是“懒”,能使用 JavaScript 一门语言完成全部事儿,为何要学更多呢? 咱们能够根据框架的特性进行分类

框架名称 特性 点评
Express 简单、实用,路由中间件等五脏俱全 最著名的Web框架
Derby.js && Meteor 同构 先后端都放到一块儿,模糊了开发便捷,看上去更简单,实际上上对开发来讲要求更高
Sails、Total 面向其余语言,Ruby、PHP等 借鉴业界优秀实现,也是 Node.js 成熟的一个标志
MEAN.js 面向架构 相似于脚手架,又指望同构,结果只是蹭了热点
Hapi和Restfy 面向Api && 微服务 移动互联网时代Api的做用被放大,故而独立分类。尤为是对于微服务开发更是利器
ThinkJS 面向新特性 借鉴ThinkPHP,并慢慢走出本身的一条路,对于Async函数等新特性支持,无出其右,新版v3.0是基于Koa v2.0的做为内核的
Koa 专一于异步流程改进 下一代Web框架
Egg 基于Koa,在开发上有极大便利 企业级Web开发框架

对于框架选型

  • 业务场景、特色,没必要为了什么而什么,避免本末倒置
  • 自身团队能力、喜爱,有时候技术选型决定团队氛围的,须要平衡激进与稳定
  • 出现问题的时候,有人可以作到源码级定制。Node.js 已经有8年历史,但模块完善程度参差不齐,若是不慎踩到一个坑里,须要团队在无外力的状况可以搞定,不然会影响进度

Tips:我的学习求新,企业架构求稳,无非喜爱与场景而已 Web编程核心

  • 异步流程控制(前面讲过了)

  • 基本框架 Koa或Express,新手推荐Express,毕竟资料多,上手更容易。若是有必定经验,推荐Koa,其实这些都是为了了解Web编程原理,尤为是中间件机制理解。

  • 数据库 mongodb或mysql都行,mongoose和Sequelize、bookshelf,TypeOrm等都很是不错。对于事物,不是Node.js的锅,是你选的数据库的问题。另一些偏门,想node连sqlserver等估计还不成熟,我是不会这样用的。

  • 模板引擎, ejs,jade,nunjucks。理解原理最好。尤为是extend,include等高级用法,理解布局,复用的好处。其实先后端思路都是同样的。

  • Node 的书几乎都过期了,我该买哪本?

  • Node 用途那么多,我该从哪里学起?

  • Node Web 框架那么多,我该怎么选?

相关文章
相关标签/搜索