node
nodejs
学着玩
输出
有颜色的输出
底层原生
封装好的
进度条
输入
从命令行获取参数
例如:
或
获取参数值的方法是使用 Node.js 中内置的 process
对象。
它公开了 argv
属性,该属性是一个包含所有命令行调用参数的数组。
第一个参数是 node
命令的完整路径。
第二个参数是正被执行的文件的完整路径。
所有其他的参数从第三个位置开始。
可以使用循环迭代所有的参数(包括 node 路径和文件路径):
也可以通过创建一个排除了前两个参数的新数组来仅获取其他的参数:
如果参数没有索引名称,例如:
则可以这样访问:
如果是这种情况:
但是需要在每个参数名称之前使用双破折号:
接受标准输入
模块系统
导入
只可以导入被公开的
导出
使用module.exports导出
将对象赋值给
module.exports
(这是模块系统提供的对象),这会使文件只导出该对象:
将要导出的对象添加为
exports
的属性。这种方式可以导出多个对象、函数或数据:
或直接
在另一个文件中,则通过引用导入的属性来使用它:
或
module.exports
和 export
之间有什么区别?
前者公开了它指向的对象。 后者公开了它指向的对象的属性。
NPM
安装所有依赖
如果项目具有 package.json
文件,则通过运行:
它会在 node_modules
文件夹(如果尚不存在则会创建)中安装项目所需的所有东西。
安装单个软件包
也可以通过运行以下命令安装特定的软件包:
通常会在此命令中看到更多标志:
--save
安装并添加条目到package.json
文件的 dependencies。--save-dev
安装并添加条目到package.json
文件的 devDependencies。
区别主要是,devDependencies
通常是开发的工具(例如测试的库),而 dependencies
则是与生产环境中的应用程序相关。
更新软件包
通过运行以下命令,更新也变得很容易:
npm
会检查所有软件包是否有满足版本限制的更新版本。
也可以指定单个软件包进行更新:
运行任务
package.json 文件支持一种用于指定命令行任务(可通过使用以下方式运行)的格式:
例如:
使用此特性运行 Webpack 是很常见的:
因此可以运行如下,而不是输入那些容易忘记或输入错误的长命令:
查看所有安装的包
查看指定包的信息
安装旧版本
package.json
package.json
文件是项目的清单。 它可以做很多完全互不相关的事情。 例如,它是用于工具的配置中心。 它也是npm
和yarn
存储所有已安装软件包的名称和版本的地方。
version
表明了当前的版本。name
设置了应用程序/软件包的名称。description
是应用程序/软件包的简短描述。main
设置了应用程序的入口点。private
如果设置为true
,则可以防止应用程序/软件包被意外地发布到npm
。scripts
定义了一组可以运行的 node 脚本。dependencies
设置了作为依赖安装的npm
软件包的列表。devDependencies
设置了作为开发依赖安装的npm
软件包的列表。engines
设置了此软件包/应用程序在哪个版本的 Node.js 上运行。browserslist
用于告知要支持哪些浏览器(及其版本)。
以上所有的这些属性都可被 npm
或其他工具使用。
dependencies
设置作为依赖安装的 npm
软件包的列表。
当使用 npm 或 yarn 安装软件包时:
该软件包会被自动地插入此列表中。
package-lock.json
简单理解:用来锁版本
==事件循环==
事件循环是了解 Node.js 最重要的方面之一。
为什么这么重要? 因为它阐明了 Node.js 如何做到异步且具有非阻塞的 I/O,所以它基本上阐明了 Node.js 的“杀手级应用”,正是这一点使它成功了。
Node.js JavaScript 代码运行在单个线程上。 每次只处理一件事。
这个限制实际上非常有用,因为它大大简化了编程方式,而不必担心并发问题。
只需要注意如何编写代码,并避免任何可能阻塞线程的事情,例如同步的网络调用或无限的循环。
通常,在大多数浏览器中,每个浏览器选项卡都有一个事件循环,以使每个进程都隔离开,并避免使用无限的循环或繁重的处理来阻止整个浏览器的网页。
该环境管理多个并发的事件循环,例如处理 API 调用。 Web 工作进程也运行在自己的事件循环中。
主要需要关心代码会在单个事件循环上运行,并且在编写代码时牢记这一点,以避免阻塞它。
阻塞事件循环
任何花费太长时间才能将控制权返回给事件循环的 JavaScript 代码,都会阻塞页面中任何 JavaScript 代码的执行,甚至阻塞 UI 线程,并且用户无法单击浏览、滚动页面等。
JavaScript 中几乎所有的 I/O 基元都是非阻塞的。 网络请求、文件系统操作等。 被阻塞是个异常,这就是 JavaScript 如此之多基于回调(最近越来越多基于 promise 和 async/await)的原因。
案例1
输出
案例2
输出
消息队列
当调用 setTimeout() 时,浏览器或 Node.js 会启动定时器。 当定时器到期时(在此示例中会立即到期,因为将超时值设为 0),则回调函数会被放入“消息队列”中。
在消息队列中,用户触发的事件(如单击或键盘事件、或获取响应)也会在此排队,然后代码才有机会对其作出反应。 类似 onLoad
这样的 DOM 事件也如此。
事件循环会赋予调用堆栈优先级,它首先处理在调用堆栈中找到的所有东西,一旦其中没有任何东西,便开始处理消息队列中的东西。
我们不必等待诸如 setTimeout
、fetch、或其他的函数来完成它们自身的工作,因为它们是由浏览器提供的,并且位于它们自身的线程中。 例如,如果将 setTimeout
的超时设置为 2 秒,但不必等待 2 秒,等待发生在其他地方。
ES6 作业队列
ECMAScript 2015 引入了作业队列的概念,Promise 使用了该队列(也在 ES6/ES2015 中引入)。 这种方式会尽快地执行异步函数的结果,而不是放在调用堆栈的末尾。
在当前函数结束之前 resolve 的 Promise 会在当前函数之后被立即执行。
有个游乐园中过山车的比喻很好:消息队列将你排在队列的后面(在所有其他人的后面),你不得不等待你的回合,而工作队列则是快速通道票,这样你就可以在完成上一次乘车后立即乘坐另一趟车。
示例:
这会打印:
这是 Promise(以及基于 promise 构建的 async/await)与通过 setTimeout()
或其他平台 API 的普通的旧异步函数之间的巨大区别。
Last updated