JavaScript运行时node.js基础

一、什么是node.js?

  Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时(C++语言编写),打破了过去JavaScript只能在浏览器中运行的局面。Node.js 应用程序在单个进程中运行,无需为每个请求创建新的线程。 Node.js 在其标准库中提供了一组异步的 I/O 原语,以防止 JavaScript 代码阻塞,通常,Node.js 中的库是使用非阻塞范式编写的,使得阻塞行为成为异常而不是常态。

  浏览器和 Node.js 都使用 JavaScript 作为其编程语言,构建在浏览器中运行的应用程序与构建 Node.js 应用程序完全不同。在浏览器中,js大部分时间都是与 DOM 或其他 Web 平台 API(如 Cookies)进行交互,而在 Node.js 中没有浏览器提供的 documentwindow 和所有其他对象,同样地浏览器中js没有类似访问数据库,文件系统的功能。

  它的出现使得编写JavaScript 的前端开发者无需学习JAVA\C\C++\C#等后端语言,就可以编写除客户端代码之外的服务器端代码,因为nodejs提供了访问数据库、文件系统、网络读取等与服务端语言特性相关的支持。

  Node.js有如下特点:

  • 它是一个Javascript运行环境
  • 依赖于Chrome V8引擎进行代码解释
  • 异步事件驱动
  • 非阻塞I/O
  • 轻量、可伸缩,适于实时数据交互应用
  • 单进程,单线程(这里指主线程)
  • 高性能
  • 大量的生态库

二、nodejs的安装

  Node.js 可以通过多种方式安装,所有主流平台的官方软件包都可以在 http://nodejs.cn/download/ 获得。此处以在windows中安装为例,首先下载合适自己系统的安装包,如图:

   使用该方式安装会自动将设置nodejs的环境变量(如果通过其他方式安装,可能需要设置环境变量),安装完成后打开 cmd命令行窗口 输入命令' node -v '查看版本,如果出现版本号,则表示安装成功,如图:

 三、通过nodejs运行js脚本

  在cmd命令行窗口或者编译器的cmd窗口中,使用' node *.js ' 命令可以在nodej环境中运行对应的js代码,需要注意的是如果在编译器中运行编写的完成项目,当服务启动后再次修改js代码后需要重启服务才能生效,我们可以使用 ' nodemon  *js '命令来启动,该命令支持热更新。在控制台中运行程序时可以使用CTRL+C命令可以退出正在运行的Node.js程序,同时我们也可以使用编程的方式再触发某些事件后运行process.exit(0)来终止程序。

四、编写Node.js程序

  为了快速的入门编写nodejs代码,应先熟悉如下代码示例,掌握常用的功能代码:

//process 核心模块提供了一种方便的方法,允许您以编程方式退出 Node.js 程序:process.exit()。
//默认的退出码为 0,表示成功。 不同的退出代码有不同的含义,可以在 http://nodejs.cn/api/process.html#process_exit_codes 阅读更多关于退出代码的信息。
process.exit(0)

//Express 是一个在底层使用 http 模块的框架,app.listen() 返回一个 http 实例。 如果您需要使用 HTTPS 为您的应用程序提供服务,则使用 https.createServer,因为 app.listen 仅使用 http 模块。
const express = require('express')
const app = express()

//监听请求路径
app.get('/', (req, res) => {
  res.send('Hi!')
})

//监听3000端口
app.listen(3000, () => console.log('Server ready'))

//调用 process.exit(),则任何当前待处理或正在运行的请求都将被中止。 这并不好。我们可以通过传递信号SIGTERM ,并使用进程信号句柄处理它
process.on('SIGTERM', () => {
  server.close(() => {
    console.log('Process terminated')
  })
})

//从程序内部,在另一个函数中发送信号终止进程
process.kill(process.pid, 'SIGTERM')
//process 不需要 "require",它是自动可用的。
//Node.js 的 process 核心模块提供了 env 属性,该属性承载了在启动进程时设置的所有环境变量。
//在脚本运行之前将其设置为 "production",则可告诉 Node.js 这是生产环境。
process.env.NODE_ENV  // "development"
//当使用以下命令调用 Node.js 应用程序时,可以传入任意数量的参数,参数可以是独立的,也可以具有键和值。
//获取参数值的方法是使用 Node.js 中内置的 process 对象。它公开了 argv 属性,该属性是一个包含所有命令行调用参数的数组。
 node app.js name=joe
 node app.js joe


//可以使用循环迭代所有的参数(包括 node 路径和文件路径)
process.argv.forEach((val, index) => {
  console.log(`${index}: ${val}`)
})
//Node.js 提供了 console 模块,该模块提供了大量非常有用的与命令行交互的方法。它基本上与浏览器中的 console 对象相同。
//最基础、最常用的方法是 console.log(),该方法会打印传入到控制台的字符串。如果传入对象,则它会呈现为字符串。可以传入多个变量到 console.log
//可以通过传入变量和格式说明符来格式化用语:%s 会格式化变量为字符串,%d 会格式化变量为数字,%i 会格式化变量为其整数部分,%o 会格式化变量为对象
const x = 'x'
const y = 'y'
console.log(x, y)
//会清除控制台(其行为可能取决于所使用的控制台)。
console.clear() 

//在某些情况下,打印函数的调用堆栈踪迹
const function = () => console.trace()
function()


//可以使用 time() 和 timeEnd() 轻松地计算函数运行所需的时间
const doSomething = () => console.log('测试')
const measureDoingSomething = () => {
  console.time('doSomething()')
  //做点事,并测量所需的时间。
  doSomething()
  console.timeEnd('doSomething()')
}
measureDoingSomething()
//Progress 是一个很棒的软件包,可在控制台中创建进度条。 使用 npm install progress 进行安装。
const ProgressBar = require('progress')

//以下代码段会创建一个 10 步的进度条,每 100 毫秒完成一步。 当进度条结束时,则清除定时器
const bar = new ProgressBar(':bar', { total: 10 })
const timer = setInterval(() => {
  bar.tick()
  if (bar.complete) {
    clearInterval(timer)
  }
}, 100)
//从版本 7 开始,Node.js 提供了 readline 模块来执行以下操作:每次一行地从可读流(例如 process.stdin 流,在 Node.js 程序执行期间该流就是终端输入)获取输入。
const readline = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
})

//这段代码会询问用户名,当输入了文本并且用户按下回车键时,则会发送问候语。
//question() 方法会显示第一个参数(即问题),并等待用户的输入。 当按下回车键时,则它会调用回调函数。
readline.question(`你叫什么名字?`, name => {
  console.log(`你好 ${name}!`)
  readline.close()
})
//Node.js 具有内置的模块系统。Node.js 文件可以导入其他 Node.js 文件公开的功能。当想要导入某些东西时,使用require导入,比如导入library.js公开的功能
const library = require('./library')


//默认情况下,文件中定义的任何其他对象或变量都是私有的,不会公开给外界。可以通过exports把需要的功能公开给外部,外部就可以通过require引入并使用公开的功能
const car = {
  brand: 'Ford',
  model: 'Fiesta'
}

//公开car对象
exports.car = car

 五、npm 包管理器

  npm 是 Node.js 标准的软件包管理器。在 2017 年 1 月,npm 仓库中就已有超过 350000 个软件包,这使其成为世界上最大的单一语言代码仓库,并且可以确定几乎有可用于一切的软件包。它起初是作为下载和管理 Node.js 包依赖的方式,但其现在也已成为前端 JavaScript 中使用的工具。npm具有如下功能:

  • npm 可以管理项目依赖的下载:如果项目具有 package.json 文件,则通过运行npm install,它会在 node_modules 文件夹(如果尚不存在则会创建)中安装项目所需的所有东西(这些东西就配置在package.json中)。
  • 安装单个软件包:可以通过运行以下命令 npm install <package-name> 安装特定的软件包,其中命令可以携带参数 " --save " 表示安装并添加条目到 package.json 文件的 dependencies,参数"--save-dev"安装并添加条目到 package.json 文件的 devDependencies。
  • 更新软件包:通过运行npm update或者npm update <package-name> 命令来更新所有包或指定包。
  • 版本控制:除了简单的下载外,npm 还可以管理版本控制,因此可以指定软件包的任何特定版本,或者要求版本高于或低于所需版本。指定库的显式版本还有助于使每个人都使用相同的软件包版本,以便整个团队运行相同的版本,直至 package.json 文件被更新。
  • 运行任务:通过命令 npm run <task-name> 运行指定任务,task-name在package.json 文件中的scripts节点下定义。比如如下定义中,运行npm run start 相当于运行node lib/server-production命令:
{
  "scripts": {
    "start-dev": "node lib/server-development",
    "start": "node lib/server-production""watch": "webpack --watch --progress --colors --config webpack.conf.js",
    "dev": "webpack --progress --colors --config webpack.conf.js",
    "prod": "NODE_ENV=production webpack -p --config webpack.conf.js",
  },
}

 六、npm包管理器常见问题

  • npm 将软件包安装到哪里:分为全局安装npm install -g xx和本地安装npm install xx两种方式,本地安装会安装到node_modules文件夹下,全局安装会安装到 npm root -g 输出的文件夹下。
  • 如何使用或执行 npm 安装的软件包:安装完成软件包后,只需使用 const xx=require('name') 导入到使用的地方即可直接使用。
  • package.json文件说:package.json 文件是项目的清单。 它可以做很多完全互不相关的事情。 例如,它是工具的配置中心,它也是 npm 和 yarn 存储所有已安装软件包的名称和版本的地方,例如vue项目中配置:
{
  "name": "test-project",
  "version": "1.0.0",
  "description": "A Vue.js project",
  "main": "src/main.js",
  "private": true,
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "unit": "jest --config test/unit/jest.conf.js --coverage",
    "test": "npm run unit",
    "lint": "eslint --ext .js,.vue src test/unit",
    "build": "node build/build.js"
  },
  "dependencies": {
    "vue": "^2.5.2"
  },
  "devDependencies": {
    "autoprefixer": "^7.1.2",
    "babel-core": "^6.22.1",
    "babel-eslint": "^8.2.1",
    "babel-helper-vue-jsx-merge-props": "^2.0.3",
    "babel-jest": "^21.0.2",
    "babel-loader": "^7.1.1",
    "babel-plugin-dynamic-import-node": "^1.2.0",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
    "babel-plugin-transform-runtime": "^6.22.0",
    "babel-plugin-transform-vue-jsx": "^3.5.0",
    "babel-preset-env": "^1.3.2",
    "babel-preset-stage-2": "^6.22.0",
    "chalk": "^2.0.1",
    "copy-webpack-plugin": "^4.0.1",
    "css-loader": "^0.28.0",
    "eslint": "^4.15.0",
    "eslint-config-airbnb-base": "^11.3.0",
    "eslint-friendly-formatter": "^3.0.0",
    "eslint-import-resolver-webpack": "^0.8.3",
    "eslint-loader": "^1.7.1",
    "eslint-plugin-import": "^2.7.0",
    "eslint-plugin-vue": "^4.0.0",
    "extract-text-webpack-plugin": "^3.0.0",
    "file-loader": "^1.1.4",
    "friendly-errors-webpack-plugin": "^1.6.1",
    "html-webpack-plugin": "^2.30.1",
    "jest": "^22.0.4",
    "jest-serializer-vue": "^0.3.0",
    "node-notifier": "^5.1.2",
    "optimize-css-assets-webpack-plugin": "^3.2.0",
    "ora": "^1.2.0",
    "portfinder": "^1.0.13",
    "postcss-import": "^11.0.0",
    "postcss-loader": "^2.0.8",
    "postcss-url": "^7.2.1",
    "rimraf": "^2.6.0",
    "semver": "^5.3.0",
    "shelljs": "^0.7.6",
    "uglifyjs-webpack-plugin": "^1.1.1",
    "url-loader": "^0.5.8",
    "vue-jest": "^1.0.2",
    "vue-loader": "^13.3.0",
    "vue-style-loader": "^3.0.1",
    "vue-template-compiler": "^2.5.2",
    "webpack": "^3.6.0",
    "webpack-bundle-analyzer": "^2.9.0",
    "webpack-dev-server": "^2.9.1",
    "webpack-merge": "^4.1.0"
  },
  "engines": {
    "node": ">= 6.0.0",
    "npm": ">= 3.0.0"
  },
  "browserslist": ["> 1%", "last 2 versions", "not ie <= 8"]
}

   以上所有的这些属性都可被 npm 或其他工具使用,解释如下:

  1. version 表明了当前的版本。
  2. name 设置了应用程序/软件包的名称。
  3. description 是应用程序/软件包的简短描述。
  4. main 设置了应用程序的入口点。
  5. private 如果设置为 true,则可以防止应用程序/软件包被意外地发布到 npm
  6. scripts 定义了一组可以运行的 node 脚本。
  7. dependencies 设置了作为依赖安装的 npm 软件包的列表。
  8. devDependencies 设置了作为开发依赖安装的 npm 软件包的列表。
  9. engines 设置了此软件包/应用程序在哪个版本的 Node.js 上运行。
  10. browserslist 用于告知要支持哪些浏览器(及其版本)。
  • package-lock.json作用:该文件用于锁定被安装的每个软件包的确切版本,以便产品可以以相同的方式被 100% 复制(即使软件包的维护者更新了软件包)。
  • 查看 npm 包安装的版本:运行 npm list 或者npm list -g或者 npm list  packname
  • 安装 npm 包的旧版本:先使用npm view <package> versions查看版本,再使用npm install packname@version 方式安装指定版本。
  • 使用 npm 的语义版本控制:npm包都约定版本的语义,所有版本都有3个数字,为x.y.x格式,其中第一个数字是主版本,第二个数字是次版本,第三个数字是补丁版本。当发布新的版本时,不仅仅是随心所欲地增加数字,还要遵循以下规则:
  1. 当进行不兼容的 API 更改时,则升级主版本。
  2. 当以向后兼容的方式添加功能时,则升级次版本。
  3. 当进行向后兼容的缺陷修复时,则升级补丁版本。

   该约定在所有编程语言中均被采用,每个 npm 软件包都必须遵守该约定,这一点非常重要,因为整个系统都依赖于此。

  • 卸载 npm 软件包:运行 npm uninstall <package-name>命令或者npm uninstall  --save   -g <package-name>等带参数的命令。
  • npm 依赖与开发依赖:开发依赖是仅用于开发的程序包(在devDependencies节点下),在生产环境中并不需要。 例如测试的软件包、webpack 或 Babel。当install命令添加了 -D 或 --save-dev 参数时,则会将其安装为开发依赖项。

 七、Nodejs常用模块使用

  nodejs内置了文件系统、路径、操作系统、事件、http、Buffer、流等常用模块,使用方式代码举例如下:

 八、Nodejs 文件属性

  每个文件都带有一组详细信息,可以使用 Node.js 进行检查。具体地说,使用 fs 模块提供的 stat() 方法。调用时传入文件的路径,一旦 Node.js 获得文件的详细信息,则会调用传入的回调函数,并带上两个参数(错误消息和文件属性)。文件的信息包含在属性变量中。 可以通过属性:

  • 使用 stats.isFile() 和 stats.isDirectory() 判断文件是否目录或文件。
  • 使用 stats.isSymbolicLink() 判断文件是否符号链接。
  • 使用 stats.size 获取文件的大小(以字节为单位)。
const fs = require('fs')
fs.stat('/Users/joe/test.txt', (err, stats) => {
  if (err) {
    console.error(err)
    return
  }

  stats.isFile() //true
  stats.isDirectory() //false
  stats.isSymbolicLink() //false
  stats.size //1024000 //= 1MB
})

 

posted @ 2024-03-06 00:12  我若安好,便是晴天  阅读(45)  评论(0编辑  收藏  举报