1. 程式人生 > >NodeJs 入門到放棄 — 入門基本介紹(一)

NodeJs 入門到放棄 — 入門基本介紹(一)

### 碼文不易啊,轉載請帶上本文連結呀,感謝感謝 https://www.cnblogs.com/echoyya/p/14450905.html [toc] ### NodeJs 介紹 Node.js 就是執行在服務端的 JavaScript。是基於Chrome V8 引擎的JavaScript `執行環境`,簡單理解就是一個可以讓JavaScript脫離瀏覽器,執行的平臺,並對JavaScript功能進行了增強(檔案系統,模組,包,作業系統API,網路通訊,資料庫操作等) 與JavaScript的區別:Node.js 是執行環境,JavaScript是一門程式語言 ![](https://img2020.cnblogs.com/blog/1238759/202102/1238759-20210226101511065-1273316961.png) ### NodeJs 執行使用 - 安裝:[下載地址](https://nodejs.org/en/) - REPL模式:(Read-Evaluate-Print-Loop),即`互動式命令列解析器`,可以直接在命令列輸入`node`,啟動Node 的終端,直接編寫NodeJs程式碼,適合用來**測試和學習** - **讀取** - 讀取使用者輸入,解析輸入的 Javascript 資料結構並存儲在記憶體中。 - **執行** - 執行輸入的資料結構 - **列印** - 輸出結果 - **迴圈** - 迴圈操作以上步驟直到使用者兩次按下 **ctrl-c** 按鈕退出。 ![](https://img2020.cnblogs.com/blog/1238759/202102/1238759-20210226101540737-1369969534.png) - 執行JS檔案:` node XXX.js ` ![](https://img2020.cnblogs.com/blog/1238759/202102/1238759-20210226101609811-1879437471.png) ### 模組化 - 目前有**三種流行的模組化規範**:分別是 AMD(非同步載入 requirejs),CMD(seajs),`Commonjs(同步載入,只適用於服務端 NodeJs平臺)` - NodeJs採用模組方式管理和組織程式碼,NodeJs所有的功能都存在每個模組中 #### 模組組成 模組:一個具有特定功能的檔案就是一個模組,模組之間相互獨立,同時也可以相互共享資料,需要暴露資料和引入操作 ``` /** * NodeJs模組組成: * 所有使用者編寫的程式碼都在模組中,模組就是檔案(函式) * 該函式有五個引數: * exports: 暴露物件,可以將模組中的資料暴露給引用模組 * require: 引入模組,用於在A模組中引入B模組,並將B模組暴露的資料賦值給變數 * module: 模組物件,包含了當前模組的所有資訊 * __filename: 當前模組的檔名 * __dirname: 當前模組所在的路徑 */ // arguments 屬性只能在函式內部使用,因此說明模組就是函式 console.log(arguments.callee.toString()); // 打印出函式體本身 exports.username = 'Echoyya' // console.log(arguments); // 可以將引數分別列印 ``` #### require 函式 作用:在當前模組載入另一模組,不同型別的模組,引入模組時也有一些差異 模組分類: 1. 自定義模組:開發者自己編寫的功能檔案即為自定義模組 - 若子模組沒有暴露資料時,返回空物件 - 自定義模組必須加`./`,否則nodejs查詢模組預設在`node_modules`目錄中查詢 - 主模組:整個專案的啟動模組,有且僅有一個,對其他模組進行整合排程 ```js // hello.js var obj = require('./test') console.log(obj); // {} // test.js console.log('Echoyya'); ``` 2. 第三方模組:第三方程式設計師或公司開發的模組,先安裝再使用,npm 安裝,require 使用 3. 系統模組:nodejs開發團隊提供的功能模組 ,直接引入使用即可,無需安裝 > 模組初始化:當一個模組被多次引入時,只執行一次,將暴露物件exports直接寫入快取,後續就直接讀取快取 ![](https://img2020.cnblogs.com/blog/1238759/202102/1238759-20210226101643431-1680871073.png) #### exports 匯出物件 作用:是當前模組的匯出物件,用於匯出模組公有方法和屬性,其他模組通過require函式載入使用 `exports.屬性 = 值` `exports.方法 = 函式` ``` // test.js 暴露屬性和方法 var username = 'Echoyya' function showName(){ console.log('test模組:showName方法被呼叫'); console.log(module.exports === exports); // true } exports.name = username exports.show = showName // hello.js 載入呼叫 var obj = require('./test') obj.show() ``` - exports物件 和 module.exports物件,指同一個記憶體空間, module.exports物件才是真正的暴露物件 - `exports物件 是 module.exports物件的引用`,不能改變指向,只能新增屬性和方法,若直接改變exports 的指向,則返回空物件 - **console.log(module.exports === exports); // true** - 若想直接暴露對應的showName函式,可以改變module.exports的指向,module.exports=showName ![](https://img2020.cnblogs.com/blog/1238759/202102/1238759-20210226101730889-610964327.png) #### module 模組物件 module.exports :暴露物件,exports物件只是對其的引用 ``` // 常用語法: module.exports.屬性 = 值 module.exports.方法 = 函式 module.exports = 物件或函式 ``` 以下內容作為了解即可: - module.id:模組ID,模組名稱 - module.parent:模組的父級 - module.filename:模組的檔名和路徑 - module.children:子模組列表 - module.paths:模組查詢路徑,預設查詢當前目錄下的node_modules,若沒有則向上查詢,直至根目錄,如果另外配置了NODE_PATH環境變數,也會去查詢 ### npm和package.json檔案 **npm**:(Node Package Manager)是基於Nodejs的包管理工具,能解決NodeJS程式碼部署上的很多問題 - 允許使用者從NPM伺服器下載別人編寫的第三方包到本地使用。 - 允許使用者將自己編寫的包或命令列程式上傳到NPM伺服器供別人使用。 - 新版的nodejs已經集成了npm,可以通過輸入 **"npm -v"** 來測試是否成功安裝 **package.json**:以JSON格式描述nodejs專案的包描述檔案,建立語法:`npm init `或 `npm init -y`(預設全部yes) ### Nodejs 作用域 Nodejs中一個檔案即是一個模組,由於nodejs在執行時會將使用者編寫的所有程式碼都封裝在函式中,因此模組中使用者使用var宣告的變數或函式都是區域性的只能在該模組中使用。 共享資料給其他模組使用的方法: 1. 暴露物件:module.exports,文章上述有詳細的描述 2. `全域性物件`:nodejs中沒有window物件,但是有`global物件`(儘量少用),可以把共享資料掛載到global物件上,以供其他模組使用,使用時global關鍵字可以省略 ![](https://img2020.cnblogs.com/blog/1238759/202102/1238759-20210226101804170-926070107.png) ### Nodejs 非同步程式設計實現的三種方式 #### 1. 回撥函式 Node.js 非同步程式設計的直接體現就是回撥,Node 使用了大量的回撥函式並且Node 所有 API 都支援回撥函式。這就大大提高了 Node.js 的效能,可以處理大量的併發請求。 回撥函式:又稱回撥,將A函式的引用地址作為引數傳遞給B函式(呼叫者),B函式在執行過程中根據時機或條件決定是否呼叫A函式,A函式就是回撥函式,一般作為函式的最後一個引數出現。 `非同步一定有回撥函式`,但是`回撥函式不一定是非同步` ``` // 非同步一定有回撥函式 setTimeout(function () { console.log('1'); }, 0); console.log(2) // 輸出結果 2 1 // 回撥函式不一定是非同步 console.log(1); var arr = ['a','b','c'] arr.forEach(function(v){ console.log(v); }) console.log(3); // 輸出結果 1 a b c 3 即為同步 ``` #### 2. 事件 ``` var http = require('http') var server = http.createServer() server.on('request',function(req, res){ res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"}) // 設定編碼 res.write('

訪問nodejs服務

') res.end() }) server.listen(80,function(){ console.log('伺服器執行.....'); }) ``` #### 3. Promise 物件 promise是ES6中新增的物件,用於對非同步的操作進行訊息的傳遞,由於非同步的返回結果時間順序並不可控,使用promise就可以將非同步操作以同步操作的流程表達出來,避免了層層巢狀的回撥函式。解決了以往的回撥地獄現象。並提供統一的介面,使得控制非同步操作更加容易。 promise有三種狀態:`pending`(進行中)、`resolved`(已成功)和`rejected`(已失敗),物件的狀態不受外界影響。 `Promise`物件的狀態改變,只有兩種可能:從`pending`變為``resolved``和從`pending`變為`rejected`。一旦發生,狀態就凝固不會再變。任何時候都可以得到這個結果。 Promise 提供的API遠不止這些,還有許多強大的介面,更多具體用法,請參考阮老師的 [[ECMAScript 6 入門](https://es6.ruanyifeng.com/#docs/promise)] ``` var fs = require('fs') function asyncReadFile(url){ return new Promise(function(resolved, rejected){ fs.readFile(url,function(err,data){ if(err) { rejected(err) }else{ resolved(data.toString()) } }) }) } var p1 = asyncReadFile('./file1.txt') var p2 = asyncReadFile('./file2.txt') // 非同步的返回結果時間順序並不可控,p2可能會先執行完畢, p1.then(function(value){ console.log('p1',value); },function(err){ console.log(err); }) p2.then(function(value){ console.log('p2',value); },function(err){ console.log(err); }) // Promise.all()用於將多個Promise例項,包裝成一個新的Promise例項 // 陣列格式傳入多個Promise例項可以執行順序 //[p1,p2] Promise.all([p1,p2]).then(function(datas){ console.log('[p1,p2]',datas); },function(errs){ console.log(errs); }) // [p2,p1] Promise.all([p2,p1]).then(function(datas){ console.log('[p2,p1]',datas); },function(errs){ console.log(errs); }) ``` ![](https://img2020.cnblogs.com/blog/1238759/202102/1238759-20210226101832001-16115332