各個平臺都有相關的包管理工具,Ubuntu
下的apt-get
,CentOS
下的yum
,macOS
下的homebrew
,便於安裝和卸載軟件。Node.js是名副其實的版本帝,版本更新之快使得上述的工具不適用,開發機器有可能須要同時存在幾個Node.js的大版本,每一個Node.js內置的npm又有版本的差別,並且,國內網絡訪問npmjs.org鏡像速度很慢,因此,推薦適用3m安裝法。前端
nvm
是一個開源的Node.js版本管理器,經過簡單的bash腳原本管理、切換多個Node.js版本。node
注意:nvm不支持windows版本,但有替代品nvm-windowsreact
安裝:jquery
# nvm 安裝
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash
# node.js 安裝 官網最新LTS
nvm install 12.13.1
複製代碼
查看環境配置:webpack
cat ~/.bash_profile
複製代碼
執行source
命令,是環境生效git
source ~/.bash_profile
複製代碼
注意:也可根據當前終端shell類型查看不一樣配置。若是是zsh,查看.zshrc,若是是bash,查看.bashrcangularjs
查看可安裝版本:github
nvm ls-remote
複製代碼
本機已安裝版本:web
nvm ls
複製代碼
版本類型:shell
tip: 通常奇數版本都是嘗試性的,通常LTS版本都是偶數
使用 nvm
安裝 Node.js 8.x
nvm install 8
複製代碼
指定默認版本:
nvm alias default 11
複製代碼
切換版本:
nvm use 12
複製代碼
npm
一般稱爲node包管理器。它的主要功能就是管理Node.js的包,包括:安裝、卸載、更新、查看、搜索、發佈等。它最開始的初衷是隻是Node.js包管理器,隨着前端技術react、webpack、browserify等發展,目前npm的定位是廣義的包管理器,包括js、react、mobile、angularjs、browsers、jquery、cordova、bower、gulp、grunt、browserify、docpad、nodebots、tessel等,是開源世界裏最大、生態最健全的包管理器。
Node.js集成了npm
,因此安裝Node.js時也一併安裝了。也可使用npm
命令來更新安裝。
[sudo] npm install npm -g
#指定版本
[sudo]npm install -g npm@2.9
複製代碼
使用場景有:
使用npm
安裝模塊:略
Node.js和其餘語言同樣,默認將模塊託管在 npmjs.org
,這是官方的registry(源),registry是指從哪一個源下載Node.js模塊,固然其餘組織或我的也是能夠自建npm registry
(源)的,這些非官方的鏡像會按期的和npm官方registry(源)進行同步,通常在10分鐘左右一次。
npm提供的配置源:
npm config set registry <registry url>
複製代碼
這個處理的問題在於切換源的時候比較麻煩。nrm
就是專門用於解決這個問題,它能夠幫助你簡單、快速的在不一樣的npm registry(源)之間進行切換,它默認內置了不少經常使用的源,包括npm、cnpm、taobao、 nj、rednpm、npmMirror,固然你能夠本身經過nrm add維護本身的源。
安裝 nrm
:
npm install -g nrm
複製代碼
測速:
➜ ~ nrm test
npm ---- 732ms
yarn --- 745ms
* cnpm --- 180ms
taobao - 226ms
nj ----- Fetch Error
npmMirror 4493ms
edunpm - Fetch Error
複製代碼
查看源:
➜ ~ nrm ls
npm -------- https://registry.npmjs.org/
yarn ------- https://registry.yarnpkg.com/
* cnpm ------- http://r.cnpmjs.org/
taobao ----- https://registry.npm.taobao.org/
nj --------- https://registry.nodejitsu.com/
npmMirror -- https://skimdb.npmjs.com/registry/
edunpm ----- http://registry.enpmjs.org/
複製代碼
切換源: 不須要記住 registry 的具體URL,使用registry的名字
nrm use <registry name>
➜ ~ nrm use taobao
Registry has been set to: https://registry.npm.taobao.org/
複製代碼
增長源:
nrm add <regsitry url>
複製代碼
目的:
瀏覽器中的異步核心技術是Ajax,異步Javascript和XML。Node.js的異步原理的核心是EventLoop。
看圖說話:
Ajax 異步處理:
Node.js 異步處理:
調用Node.js API的方法的時候,它會把具體操做和回調函數交給 EventLoop 去執行,EventLoop 維護了一個任務隊列(microTask),等異步操做執行完成,隊列中的回調函數會按照先進先出(FIFO)的順序執行。
🌰 獲取目錄下的全部文件的API
# hello-async.js
const fs = require('fs')
const path = '.'
fs.readdir(path, function(err, files) {
if (err) {
console.log(err)
return;
}
console.log(files)
})
複製代碼
# hello-sync.js
const fs = require('fs')
console.log(fs.readdirSync('.'))
複製代碼
注意:高併發場景下慎用同步寫法,否則可能會成爲性能瓶頸,跟Node.js的設計初衷是相悖的。
Node.js 中有兩種事件處理方式,callback
和 EventEmitter
。 callback
採用錯誤優先的回調方式,後者是事件驅動力裏的事件發射器。
Node.js 極其依賴異步代碼和回調來保證執行效率。Node.js SDK 中的 callback 使用 錯誤優先回調(error-first-callback)寫法。規則以下:
error
對象,若是發生錯誤,該對象會做爲第一個參數返回,正常返回null。🌰見 hello-err-first.js
這個🌰告訴咱們:
try-catch
簡單理解爲「發佈/訂閱」模式,和前端的事件機制相似,如Vue裏面的 $emit
和 $on
。
const EventEmitter = require('events')
const obsever = new EventEmitter()
obsever.on('topic', function() {
console.log('topic has occured')
})
function main() {
console.log('start')
obsever.emit('topic')
console.log('end')
}
main()
複製代碼
**注意:對於EventEmitter 的 on
來講,Node.js容許同一個事件最多指定10個回調函數,超過會發出警告。能夠經過設置setMaxListeners
方法改變。 **
Node.js採用了錯誤優先的回調寫法,致使SDK中導出的都是回調函數,若是組合調用這些函數,常常會出現回調裏嵌套回調的問題。這種寫法稱之爲回調地獄。
🌰
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
複製代碼
Node.js如何解決回調地獄:
Promise
🌰 1
const fs = require('fs')
function hello(file) {
return new Promise(function(resolve, reject ) {
fs.readFile(file, function(err, data) {
if (err) {
reject(err)
} else {
resolve(data.toString())
}
})
})
}
hello('./hello-events.js')
.then(function(res) {
console.log(res)
})
.catch(function(err) {
console.log(err)
})
複製代碼
使用Promise 實例處理異步流程控制,約定了每一個函數的返回值都是 Promise 對象,所以均可以使用 then
方法處理。
使用reject
和 resolve
重塑流程:
const fs = require('fs')
function hello(file) {
return new Promise(function(resolve, reject ) {
fs.readFile(file, function(err, data) {
if (err) {
reject(err)
} else {
resolve(data.toString())
}
})
})
}
hello('../main.js')
.then (function(data) {
return new Promise(function(resolve, reject) {
console.log('promise1\n', data)
resolve(data)
})
})
.then(function(data) {
return new Promise(function(resolve, reject) {
console.log('promise2\n', data)
resolve(1)
})
})
.then(function(data) {
return new Promise(function(resolve, reject) {
console.log('promise3\n', data)
reject(new Error('reject'))
})
})
.catch(function(err) {
console.log('catch\n', err)
})
複製代碼
const fs = require('fs')
function hello(file) {
return new Promise(function(resolve, reject ) {
fs.readFile(file, function(err, data) {
if (err) {
reject(err)
} else {
resolve(data.toString())
}
})
})
}
hello('./main.js')
.then (function(data) {
return new Promise(function(resolve, reject) {
console.log('promise1\n', data)
resolve(data)
})
.then(function(res) {
return new Promise(function(resolve, reject) {
console.log('promise2\n', data)
resolve(1)
})
})
.catch(function(err) {
console.log('catch', err)
})
})
.catch(function(err) {
console.log('catch\n', err)
})
複製代碼
const fs = require('fs')
function hello(file) {
return new Promise(function(resolve, reject ) {
fs.readFile(file, function(err, data) {
if (err) {
reject(err)
} else {
resolve(data.toString())
}
})
})
}
const step1 = function(data) {
return new Promise(function(resolve, reject) {
console.log('promise1\n', data)
resolve(data)
})
.then(function(res) {
return new Promise(function(resolve, reject) {
console.log('promise2\n', data)
resolve(1)
})
})
.catch(function(err) {
console.log('catch', err)
})
}
const step2 = function(data) {
return new Promise(function(resolve, reject) {
console.log('promise3\n', data)
reject(new Error('reject'))
})
}
hello('./hello-sync.js')
.then(step1)
.then(step2)
.catch(function(err) {
console.log(err)
})
複製代碼
# hello-reflow-module.js
const hello = require('./tasks/hello')
const step1 = require('./tasks/step1')
const step2 = require('./tasks/step2')
hello('../hello-json.json')
.then(step1)
.then(step2)
.catch(function(err) {
console.log(err)
})
複製代碼
書籍:《狼書(卷1):更了不得的Node.js》
社區:cnodejs