node筆記

 

Node 簡介

客戶端的JavaScript是怎樣的

  • 什麼是 JavaScript?+是一個腳本語言+運行在瀏覽器(瀏覽器的js解析內核 v8)+實現用戶的交互 (interactive)php

    • 變量 賦值 循環 邏輯 判斷 分支 對象 函數。。。。html

    • dom 操做前端

    • bom 操做java

    • ajax node

  • JavaScript 的運行環境?+瀏覽器內核解析內核 es6python

  • 瀏覽器中的 JavaScript 能夠作什麼?linux

  • 瀏覽器中的 JavaScript 不能夠作什麼?(不安全)+訪問數據庫+不能對文件進行操做 +對os 進行操做+緣由 是不安全 和瀏覽器運行機制有關git

  • 在開發人員能力相同的狀況下編程語言的能力取決於什麼?es6

    +cordova hbuilder 平臺 platform+java java虛擬機 (運行平臺)+php php虛擬機+c# .net framework mono+js 解析內核 chrome v8 github

  • JavaScript 只能夠運行在瀏覽器中嗎?+不是

爲何是JavaScript

  • node js 不是由於js 產生的

  • node 選擇了js

  • Ryan dahl

  • 2009 2 月份 node有想法

  • 2009 5 月份 githup 開源

  • 2009 11月份 jsconf 講解推廣node

  • 2010年末 被xxx公司收購

  • 2018 發佈有重大bug

  • npm

  • githup 世界上最大的同性交友網站 碼雲

what is node ?

  • Node.js 是一個基於Chrome V8 引擎的JavaScript運行環境

  • Node.js使用了一個事件驅動、非阻塞式I/O的模型,使其輕量又高效

  • Node.js的包管理工具npm,是全球最大的開源庫生態系統

  • 官網 http://nodejs.cn/

  • npm 插件官網:https://www.npmjs.com/

環境配置

Node的安裝

  • 安裝包安裝

    • 官網下載對應的安裝包

    • 一路next

  • nvm安裝(有一個相似的工具:n)

    • Node Version Manager(Node版本管理工具)

    • 因爲之後的開發工做可能會在多個Node版本中測試,並且Node的版本也比較多,因此須要這麼款工具來管理

    • 下載地址

      基本命令
      nvm -v 查看版本號
      nvm list 查看列表
      nvm install 版本號 安裝node
      nvm uninstall 版本號 卸載node

       

       

相關版本

  • node版本常識

    • 偶數版本爲穩定版 (0.6.x ,0.8.x ,0.10.x)

    • 奇數版本爲非穩定版(0.7.x ,0.9.x ,0.11.x)

    • LTS(Long Term Support)

    • LTS和Current區別

  • 操做方式:

    • 從新下載最新的安裝包;

    • 覆蓋安裝便可;

  • 問題:

    • 之前版本安裝的不少全局的工具包須要從新安裝

    • 沒法回滾到以前的版本

    • 沒法在多個版本之間切換(不少時候咱們要使用特定版本)

Windows下經常使用的命令行操做

  • 切換當前目錄(change directory):cd

  • 建立目錄(make directory):mkdir

  • 查看當前目錄列表(directory):dir

    • 別名:ls(list)

  • 清空當前控制檯:cls

    • 別名:clear

  • 刪除文件:del

    • 別名:rm

注意:全部別名必須在新版本的 PowerShell (linux系統)中使用

常見問題

  • Python環境丟失

  • Node中有些第三方的包是以C/C++源碼的方式發佈的,須要安裝後編譯,確保全局環境中可使用python命令,python 版本推薦2.7.0

  • 環境變量丟失

  • 部分電腦安裝完畢以後沒有環境變量須要手動配置

  • Windows中環境變量分爲系統變量和用戶變量

  • 環境變量的變量名是不區分大小寫的

  • PATH 變量:只要添加到 PATH 變量中的路徑,均可以在任何目錄下

  • 目的能夠在任何地方調起node命令

##模塊,包 commonjs

commonjs規範

前端模塊化:AMD,CMD,Commonjs

Node 應用由模塊組成,採用 CommonJS 模塊規範。

定義module

每一個文件就是一個模塊,有本身的做用域。在一個文件裏面定義的變量、函數、類,都是私有的,對其餘文件不可見。

暴露接口

CommonJS規範規定,每一個模塊內部,module變量表明當前模塊。這個變量是一個對象,它的exports屬性(即module.exports)是對外的接口。加載某個模塊,實際上是加載該模塊的module.exports屬性。

  var x = 5;
var addX = function (value) {
 return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
引用

require方法用於加載模塊。

  var example = require('./example.js');
console.log(example.x); // 5
console.log(example.addX(1)); // 6

模塊的分類

  • 內置模塊

 const process = require('process')
const path = require('path')
console.log(process.version)
console.log(path.resolve('../'))
  • 第三方模塊

    const request=require("request");
console.log(request)
request.get('http://api.douban.com/v2/movie/in_theaters', (err, response, body) => {
if (!err) {
  // console.log(body);
  console.log(JSON.parse(body))
} else {
  console.log(err);
}
})
  • 自定義模塊

###npm 使用入門

官網:https://www.npmjs.com/

安裝:無需安裝

查看當前版本:

 $ npm -v

更新:

 $ npm install npm@latest -g

初始化工程

 $ npm init

$ npm init --yes 默認配置

安裝包

使用npm install會讀取package.json文件來安裝模塊。安裝的模塊分爲兩類 dependencies和devDependencies,分別對應生產環境須要的安裝包和開發環境須要的安裝包。

 $ npm install

$ npm install <package_name>

$ npm install <package_name> --save

$ npm install <package_name> --save-dev

更新模塊

 $ npm update

卸載模塊

 $ npm uninstall <package_name>

$ npm uninstall --save lodash

配置npm源

  • 臨時使用, 安裝包的時候經過--registry參數便可

    $ npm install express --registry https://registry.npm.taobao.org

  • 全局使用

      $ npm config set registry https://registry.npm.taobao.org
    // 配置後可經過下面方式來驗證是否成功
    npm config get registry
    // 或
    npm info express
  • cnpm 使用

     // 安裝cnpm
    npm install -g cnpm --registry=https://registry.npm.taobao.org

    // 使用cnpm安裝包
    cnpm install express

經常使用的內置模塊

node 經常使用內置api

(1) URL 網址解析 解析URL相關網址信息 url.parse(urlString[, parseQueryString[, slashesDenoteHost]]) url.format(urlObject) url.resolve(from, to)(2) QueryString 參數處理 querystring.escape(str) querystring.unescape(str) querystring.parse(str[, sep[, eq[, options]]]) querystring.stringify(obj[, sep[, eq[, options]]])(3) HTTP 模塊概要 http.createServer(options) http.get(options[, callback]) 簡易的爬蟲 代理跨域處理(4) 事件 events 模塊(5) 文件fs模塊 打印目錄樹(6) Stream 流模塊 歌詞播放 音樂下載(8) request 方法

二、Node.js 基礎應用一、應用 HTTP 模塊編寫一個小爬蟲工具(1) 利用爬蟲獲取「拉勾網」首頁列表數據 (2) 經過 npm 安裝 cheerio 模塊得到數據二、後端表單的提交要求:(1) 應用 request post 模擬提交表單

文件讀取

Node中文件讀取的方式主要有:

fs.readFile(file[, options], callback(error, data))

fs.readFile('c:\\demo\1.txt', 'utf8', (err, data) => {
 if (err) throw err;
 console.log(data);
});

fs.readFileSync(file[, options])

try {
 const data = fs.readFileSync('c:\\demo\1.txt', 'utf8');
 console.log(data);
} catch(e) {
 // 文件不存在,或者權限錯誤
 throw e;
}

fs.createReadStream(path[, options])

const stream = fs.createReadStream('c:\\demo\1.txt');
let data = ''
stream.on('data', (trunk) => {
 data += trunk;
});
stream.on('end', () => {
 console.log(data);
});

因爲Windows平臺下默認文件編碼是GBK,在Node中不支持,能夠經過iconv-lite解決

Readline模塊逐行讀取文本內容

const readline = require('readline');
const fs = require('fs');

const rl = readline.createInterface({
 input: fs.createReadStream('sample.txt')
});

rl.on('line', (line) => {
 console.log('Line from file:', line);
});

文件寫入

Node中文件寫入的方式主要有:

fs.writeFile(file, data[, options], callback(error))

fs.writeFile('c:\\demo\a.txt', new Date(), (error) => {
 console.log(error);
});

fs.writeFileSync(file, data[, options])

try {
 fs.writeFileSync('c:\\demo\a.txt', new Date());
} catch (error) {
 // 文件夾不存在,或者權限錯誤
 console.log(error);
}

fs.createWriteStream(path[,option])

var streamWriter = fs.createWriteStream('c:\\demo\a.txt');
setInterval(() => {
 streamWriter.write(`${new Date}\n`, (error) => {
   console.log(error);
});
}, 1000);

###node中的異步操做

  • fs模塊對文件的幾乎全部操做都有同步和異步兩種形式

  • 例如:readFile() 和 readFileSync()

  • 區別:

    • 同步調用會阻塞代碼的執行,異步則不會

    • 異步調用會將讀取任務下達到任務隊列,直到任務執行完成纔會回調

    • 異常處理方面,同步必須使用 try catch 方式,異步能夠經過回調函數的第一個參數

console.time('sync');
try {
 var data = fs.readFileSync(path.join('C:\\Users\\iceStone\\Downloads', 'H.mp4'));
 // console.log(data);
} catch (error) {
 throw error;
}
console.timeEnd('sync');

console.time('async');
fs.readFile(path.join('C:\\Users\\iceStone\\Downloads', 'H.mp4'), (error, data) => {
 if (error) throw error;
 // console.log(data);
});
console.timeEnd('async');
promise 對象的使用

參考資料:JavaScript Promise迷你書

  • what is Promise *Promise是抽象異步處理對象以及對其進行各類操做的組件。Promise並非從JavaScript中發祥的概念。Promise最初被提出是在 E語言中, 它是基於並列/並行處理設計的一種編程語言。如今JavaScript也擁有了這種特性,這就是JavaScript Promise

使用了回調函數的異步處理


----
getAsync("fileA.txt", function(error, result){
   if(error){// 取得失敗時的處理
       throw error;
  }
   // 取得成功時的處理
});
----
<1> 傳給回調函數的參數爲(error對象, 執行結果)錯誤優先處理

使用了回調函數的異步處理

----
var promise = getAsyncPromise("fileA.txt");
promise.then(function(result){
   // 獲取文件內容成功時的處理
}).catch(function(error){
   // 獲取文件內容失敗時的處理
});
----
<1> 返回promise對象
  • 建立Promise對象 *

var promise = new Promise(function(resolve, reject) {
  // 異步處理
  // 處理結束後、調用resolve 或 reject
  resolve('成功處理')
  reject('錯誤處理')
});
  • 使用實例 *

  1. 建立一個priomise 對象並返回new Promise(fn)

  2. 在fn 中指定異步等處理

    • 處理結果正常的話,調用resolve(處理結果值)

    • 處理結果錯誤的話,調用 reject(Error對象)

function asyncFunction() {
   
   return new Promise(function (resolve, reject) {
       setTimeout(function () {
           resolve('Async Hello world');
      }, 16);
  });
}

asyncFunction().then(function (value) {
   console.log(value);    // => 'Async Hello world'
}).catch(function (error) {
   console.log(error);
});
  • Promise的狀態

用new Promise 實例化的promise對象有如下三個狀態。

  • "has-resolution" - Fulfilled resolve(成功)時。

  • "has-rejection" - Rejected reject(失敗)時

  • "unresolved" - Pending 既不是resolve也不是reject的狀態。也就是promise對象剛被建立後的初始化狀態等

promise對象的狀態,從Pending轉換爲Fulfilled或Rejected以後, 這個promise對象的狀態就不會再發生任何變化。

也就是說,Promise與Event等不一樣,在.then 後執行的函數能夠確定地說只會被調用一次。

另外,Fulfilled和Rejected這兩個中的任一狀態均可以表示爲Settled(不變的)。

Settledresolve(成功) 或 reject(失敗)。

從Pending和Settled的對稱關係來看,Promise狀態的種類/遷移是很是簡單易懂的。

當promise的對象狀態發生變化時,用.then 來定義只會被調用一次的函數。

路徑模塊

在文件操做的過程當中,都必須使用物理路徑(絕對路徑),path模塊提供了一系列與路徑相關的 API

console.log('join用於拼接多個路徑部分,並轉化爲正常格式');
const temp = path.join(__dirname, '..', 'lyrics', './友誼之光.lrc');
console.log(temp);

console.log('獲取路徑中的文件名');
console.log(path.basename(temp));

console.log('獲取路徑中的文件名並排除擴展名');
console.log(path.basename(temp, '.lrc'));

console.log('====================================');

console.log('獲取不一樣操做系統的路徑分隔符');
console.log(process.platform + '的分隔符爲 ' + path.delimiter);

console.log('通常用於分割環境變量');
console.log(process.env.PATH.split(path.delimiter));

console.log('====================================');

console.log('獲取一個路徑中的目錄部分');
console.log(path.dirname(temp));

console.log('====================================');

console.log('獲取一個路徑中最後的擴展名');
console.log(path.extname(temp));

console.log('====================================');

console.log('將一個路徑解析成一個對象的形式');
const pathObject = path.parse(temp);
console.log(pathObject);

console.log('====================================');

console.log('將一個路徑對象再轉換爲一個字符串的形式');
// pathObject.name = '我終於失去了你';
pathObject.base = '我終於失去了你.lrc';
console.log(pathObject);

console.log(path.format(pathObject));

console.log('====================================');

console.log('獲取一個路徑是否是絕對路徑');
console.log(path.isAbsolute(temp));
console.log(path.isAbsolute('../lyrics/愛的代價.lrc'));

console.log('====================================');

console.log('將一個路徑轉換爲當前系統默認的標準格式,並解析其中的./和../');
console.log(path.normalize('c:/develop/demo\\hello/../world/./a.txt'));

console.log('====================================');

console.log('獲取第二個路徑相對第一個路徑的相對路徑');
console.log(path.relative(__dirname, temp));

console.log('====================================');

console.log('以相似命令行cd命令的方式拼接路徑');
console.log(path.resolve(temp, 'c:/', './develop', '../application'));

console.log('====================================');

console.log('獲取不一樣平臺中路徑的分隔符(默認)');
console.log(path.sep);

console.log('====================================');

console.log('容許在任意平臺下以WIN32的方法調用PATH對象');
// console.log(path.win32);
console.log(path === path.win32);

console.log('====================================');

console.log('容許在任意平臺下以POSIX的方法調用PATH對象');
console.log(path === path.posix);

express


官網:http://www.expressjs.com.cn/

express 環境搭建

安裝

 $ npm install express --save

快速開始

 const express = require('express')
   const app = express()
   app.get('/', (req, res) => res.send('Hello World!'))
   app.listen(3000, () => console.log('Example app listening on port 3000!'))

express 路由配置

let express=require('express')
let router=express.Router()
// 該路由使用的中間件
router.use((req,res,next)=>{
next()
});
// 定義網站主頁的路由
router.post('/addFood', function(req, res) {
console.log('hahaha')
 // res.send('這裏是admin的登陸');
});
// 定義 about 頁面的路由
router.post('/regist', function(req, res) {
 res.send('這裏是admin的註冊側');
});

module.exports = router;

app.use('/admin',admin)

傳遞數據的獲取

get
req.query
post
req.body
body-parser

設置中文格式
res.set('Content-Type','text/plain,charset=utf8')

請求模擬工具 postman

靜態資源配置


app.use(express.static('public'))

app.use('/static', express.static('public'))

app.use('/static', express.static(path.join(__dirname, 'public')))

mongod

安裝配置

Mongodb官網下載最新版本的Mongodb下載地址

下載msiwindow安裝包,能夠裝到C盤或者D盤目錄下

配置

因爲我是安裝在D盤的環境下

D:\Program Files (x86)\MongoDB\Server\3.2\bin

因此在bin文件夾下找到mongod.exe命令,而後經過管理員執行mongod --dbpath x路徑x,路徑能夠是任何地方,我這裏選擇在D盤的MongoDB目錄下,固然路徑不要包含特殊的字符串,好比Program Files (x86)也不行

mongod --dbpath D:\mongodb\data\db

命令行

通過上面的配置以後,就能夠返回bin目錄下找到mongo.exe命令,並管理員下執行,就能夠出現mongodb的命令行模式

D:\Program Files (x86)\MongoDB\Server\3.2\bin

而後就可使用下面的命令來測試了

mongod

db.help()//幫助
db.stats()//統計

顯示數據庫

show dbs

檢查當前選擇的數據庫

db

添加數據庫

數據庫名爲數據庫建立的名字,使用該命令後會默認切換到對應的數據庫,而且在數據庫中添加選項,數據庫信息才顯示,若是默認就有該數據庫,那就是切換到對應的數據庫裏面

use 數據庫名

刪除數據庫

先切換到對應的數據庫,而後再執行db.dropDatabase()刪除該數據庫

use 數據庫名
//switched to db 數據庫名
db.dropDatabase()

顯示集合

用一下命令能夠檢查建立的集合

show collections

添加集合

在建立完數據庫以後,咱們就能夠建立集合

db.createCollection(集合名字name,設置參數options[對象類型])

name是要建立的集合的名稱。 options是一個文檔,用於指定集合的配置

參數 類型 描述name String 要建立的集合的名稱options Document (可選)指定有關內存大小和索引的選項options參數是可選的,所以只須要指定集合的名稱。 如下是可使用的選項列表:

字段 類型 描述capped Boolean (可選)若是爲true,則啓用封閉的集合。上限集合是固定大小的集合,它在達到其最大大小時自動覆蓋其最舊的條目。 若是指定true,則還須要指定size參數。autoIndexId Boolean (可選)若是爲true,則在_id字段上自動建立索引。默認值爲false。size 數字 (可選)指定上限集合的最大大小(以字節爲單位)。 若是capped爲true,那麼還須要指定此字段的值。max 數字 (可選)指定上限集合中容許的最大文檔數。因爲option是可選,咱們也能夠不帶配置項建立集合

db.createCollection("mycollection")

刪除集合

db.collection.drop()用於從數據庫中刪除集合

db.集合名.drop()

好比咱們能夠測試如下操做

db.createCollection("wscats")//建立名爲wscats的集合
show collections//顯示該數據庫全部集合   wscats
db.wscats.drop()//刪除名爲wscats的集合

查看文檔

最簡單查看文檔的方法就是find(),會檢索集合中全部的文檔結果

db.集合名.find()

要以格式化的方式顯示結果,可使用pretty()方法。

db.集合名.find().pretty()

1.固值尋找

尋找age集合裏面全部含有屬性值爲wscats的文檔結果,至關於where name = 'wscats'

db.age.find({name:"wscats"})

2.範值尋找

操做 語法 示例 等效語句相等 {:} `db.age.find({"name":"wscats"}).pretty()` where name = 'wscats'小於 {:{$lt:}} `db.age.find({"likes":{$lt:50}}).pretty()` where likes < 50小於等於 {:{$lte:}} `db.age.find({"likes":{$lte:50}}).pretty()` where likes <= 50大於 {:{$gt:}} `db.age.find({"likes":{$gt:50}}).pretty()` where likes > 50大於等於 {:{$gte:}} `db.age.find({"likes":{$gte:50}}).pretty()` where likes >= 50不等於 {:{$ne:}} `db.age.find({"likes":{$ne:50}}).pretty()` where likes != 50

3.AND和OR尋找

AND

在find()方法中,若是經過使用將它們分開傳遞多個鍵,則mongodb將其視爲AND條件。 如下是AND的基本語法

尋找_id爲1而且name爲wscats的全部結果集

db.age.find(
  {
     $and: [
        {"_id": 1}, {"name": "wscats"}
    ]
  }
)

OR

在要根據OR條件查詢文檔,須要使用$or關鍵字。如下是OR條件的基本語法

尋找name爲corrine或者name爲wscats的全部結果集

db.age.find(
  {
     $or: [
        {"name": "corrine"}, {「name「: "wscats"}
    ]
  }
)

AND和OR等結合

至關於語句where title = "wscats" OR ( title = "corrine" AND _id < 5)

db.age.find({
 $or: [{
   "title": "wscats"
}, {
   $and: [{
     "title": "corrine"
  }, {
     "_id": {
       $lte: 5
    }
  }]
}]
})

插入文檔

文檔的數據結構和JSON基本同樣。全部存儲在集合中的數據都是BSON格式。BSON是一種類json的一種二進制形式的存儲格式,簡稱Binary JSON

要將數據插入到mongodb集合中,須要使用mongodb的insert()save()方法。

db.集合名.insert(document)

好比咱們能夠插入如下數據

db.wscats.insert({
  _id: 100,
  title: 'MongoDB Tutorials',
  description: 'node_tutorials',
  by: 'Oaoafly',
  url: 'https://github.com/Wscats/node-tutorial',
  tags: ['wscat','MongoDB', 'database', 'NoSQL','node'],
  num: 100,
})

也能夠支持插入多個,注意傳入的是數組形式

db.wscats.insert([{
  _id: 100,
  title: ‘Hello’
},{
  _id: 101,
  title: ‘World’
}])

在插入的文檔中,若是不指定_id參數,那麼mongodb會爲此文檔分配一個惟一的ObjectId要插入文檔,也可使用db.post.save(document)。若是不在文檔中指定id,那麼save()方法將與insert()方法同樣自動分配ID的值。若是指定id,則將以save()方法的形式替換包含_id的文檔的所有數據。

db.wscats.save({
  _id: 111,
  title: 'Oaoafly Wscats',
})

更新文檔

1.update()方法

尋找第一條title爲wscats的值,而且更新值title爲corrine和age爲12

db.age.update({
 'title': 'wscats'
}, {
 $set: {
   'title': 'corrine',
   'age': 12
}
})

默認狀況下,mongodb只會更新一個文檔。要更新多個文檔,須要將參數multi設置爲true,還能夠配合find方法裏面的各類複雜條件判斷來篩選結果,而後更新多個文檔

尋找全部title爲wscats的值,而且更新值title爲corrine和age爲12

db.age.update({
 'title': 'wscats'
}, {
 $set: {
   'title': 'corrine',
   'age': 12
}
}, {
 multi: true
})

2.save()方法

_id主鍵爲3的文檔,覆蓋新的值,注意_id爲必傳

db.age.save({
  '_id':3,
  'title': 'wscats'
})

刪除文檔

刪除主鍵_id爲3的文檔,默認是刪除多條

db.age.remove({
 '_id':3
})

建議在執行remove()函數前先執行find()命令來判斷執行的條件是否正確

若是你只想刪除第一條找到的記錄能夠設置justOne爲1,以下所示

db.age.remove({...},1)

所有刪除

db.age.remove({})

Limit與Skip方法

Limit

若是你須要在mongodb中讀取指定數量的數據記錄,可使用mongodb的Limit方法,limit()方法接受一個數字參數,該參數指定從mongodb中讀取的記錄條數。

db.age.find().limit(數量)

Skip

咱們除了可使用limit()方法來讀取指定數量的數據外,還可使用skip()方法來跳過指定數量的數據,skip方法一樣接受一個數字參數做爲跳過的記錄條數。

db.age.find().limit(數量).skip(數量)
//skip()方法默認值爲0

因此咱們在實現分頁的時候就能夠用limit來限制每頁多少條數據(通常固定一個值),用skip來決定顯示第幾頁(一個有規律變更的值)

排序

在mongodb中使用使用sort()方法對數據進行排序,sort()方法能夠經過參數指定排序的字段,並使用1和-1來指定排序的方式,其中1爲升序排列,而-1是用於降序排列。

1 升序排列-1 降序排列

db.集合名.find().sort({鍵值(屬性值):1})

age集合表從新根據_id主鍵進行降序排列

db.age.find().sort({
 "_id": -1
})

Node.js鏈接

安裝mongodb的模塊

npm install mongodb

1.鏈接數據庫

var MongoClient = require('mongodb').MongoClient;
//結尾是選擇數據庫名
var DB_CONN_STR = 'mongodb://localhost:27017/wscats';
MongoClient.connect(DB_CONN_STR, function(err, db) {
 console.log("鏈接成功!");
});

2.查詢數據

注意查詢回來的結果須要toArray來遍歷處理

var MongoClient = require('mongodb').MongoClient;
var DB_CONN_STR = 'mongodb://localhost:27017/wscats';

MongoClient.connect(DB_CONN_STR, function(err, db) {
 console.log("鏈接成功!");
 //選中age集合,並用find方法把結果集拿回來進行處理
 db.collection("age").find({title: "cba"}).toArray(function(err, result) {
   if (err) {
     console.log('Error:' + err);
     return;
  }
   console.log(result);
});
});

通過測試,讀取大於100條的時候會出現報錯官網解釋,能夠嘗試用forEach代替

db.collection('pokemon').find({})
.forEach(function(item){
     console.log(item)
})

查詢ID

查詢自動生成的ObjectId

var ObjectId = require('mongodb').ObjectId;
let _id = ObjectId("5bcae50ed1f2c2f5e4e1a76a");
db.collection('xxx').find({
   "_id": _id
}).forEach(function (item) {
   console.log(item)
})

3.插入數據

insert函數第一個參數是須要插入的值(能夠一個也能夠多個),第二個參數是接受一個回調函數,當值插入成功後回返回插入值得一些關鍵信息,好比_id

var MongoClient = require('mongodb').MongoClient;
var DB_CONN_STR = 'mongodb://localhost:27017/wscats';

MongoClient.connect(DB_CONN_STR, function(err, db) {
 console.log("鏈接成功!");
const db = client.db("demo");
 db.collection("age").insert([
  {
     title: "插入的值A"
  }, {
     title: "插入的值B"
  }
], function(err, result) {
   if (err) {
     console.log('Error:' + err);
     return;
  }
   console.log(result)
})
});

4.更新數據

注意若是不加$set就是徹底替換原來的那份(沒有設置的屬性值將會丟失),加上$set則只是更新對應的屬性值,其他不作改變

var MongoClient = require('mongodb').MongoClient;
var DB_CONN_STR = 'mongodb://localhost:27017/wscats';

MongoClient.connect(DB_CONN_STR, function(err, db) {
 console.log("鏈接成功!");
 db.collection("age").update({
   "_id": 1
}, {
   $set: {
     title: "你好,世界",
     skill: "js"
  }
}, function(err, result) {
   if (err) {
     console.log('Error:' + err);
     return;
  }
   //console.log(result);
});
});

5.刪除數據

var MongoClient = require('mongodb').MongoClient;
var DB_CONN_STR = 'mongodb://localhost:27017/wscats';

MongoClient.connect(DB_CONN_STR, function(err, db) {
 console.log("鏈接成功!");
 db.collection("age").remove({
   "_id": 1
}, function(err, result) {
   if (err) {
     console.log('Error:' + err);
     return;
  }
   //console.log(result);
   //關閉數據庫
   db.close();
});
});

6.關閉數據庫

db.close();

封裝自定義模塊

新建mongo.js寫入如下代碼,封裝自定義模塊,方便其餘路由複用,注意assert是node自帶的斷言模塊,用於測試代碼

參考

const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const url = 'mongodb://localhost:27017';
const dbName = 'shop';
function query(callback) {
MongoClient.connect(url, function(err, client) {
assert.equal(null, err);
console.log("Connected successfully to server");
const db = client.db(dbName);
callback(db);
client.close();
});
}
module.exports = {
query
}

在路由文件中引入和使用

var mongo = require('./mongo.js')
router.post('/addproduct', function(req, res, next) {
mongo.query(function(db) {
db.collection("product").insertMany([req.body], function(err, result) {
console.log("Inserted 1 document into the collection");
res.send('respond with a resource');
});
})
});

mongoose

可視化

 

Socket

socket.io

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>socket.io</title>
 <script src="socket.io.js" charset="utf-8"></script>
</head>
<body>
 <h1>gp6 交流區</h1>
 <div id="content" name="name" style="overflow-y: scroll; width: 400px; height: 300px; border: solid 1px #000"></div>
 <br />
 <div>
   <input type="text" id="msg" style="width: 200px;">
 </div>
 <button id="submit">提交</button>
 <script>
   var socket = io.connect('http://10.9.164.98:8081');
   const content = document.getElementById('content')
   document.querySelector('#submit')
    .addEventListener('click', function () {
       var msg2 = msg.value
       socket.emit('receive', msg2)
       msg.value = ''
       content.innerHTML += msg2 + '<br/>'
    }, false)

     socket.on('message', function(msg){
       content.innerHTML += msg + '<br/>'
    })
 </script>
</body>
</html>

server.js

var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);

app.use(express.static(__dirname + '/client'))

io.on('connection', function (socket) {
 setInterval(function () {
   socket.emit('list', 'abc')
}, 1000)
 socket.broadcast.emit('list', 'test');
 socket.on('backend', (msg) => {
   console.log(msg);
})

 socket.on('receive', (msg) => {
   socket.broadcast.emit('message', msg);
})
});

server.listen(8081, '10.9.164.98');

net模塊

serverCode

const net = require('net')

const server = new net.createServer()

let clients = {}
let clientName = 0

server.on('connection', (client) => {
 client.name = ++clientName
 clients[client.name] = client

 client.on('data', (msg) => {
   // console.log('客戶端傳來:' + msg);
   broadcast(client, msg.toString())
})

 client.on('error', (e) => {
   console.log('client error' + e);
   client.end()
})

 client.on('close', (data) => {
   delete clients[client.name]
   console.log(client.name + ' 下線了');
})
})

function broadcast(client, msg) {
 for (var key in clients) {
   clients[key].write(client.name + ' 說:' + msg)
}
}

server.listen(9000)

clientCode

var net = require('net')
const readline = require('readline')

var port = 9000
var host = '127.0.0.1'

var socket = new net.Socket()

socket.setEncoding = 'UTF-8'

socket.connect(port, host, () => {
 socket.write('hello.')
})

socket.on('data', (msg) => {
 console.log(msg.toString())
 say()
})

socket.on('error', function (err) {
 console.log('error' + err);
})

socket.on('close', function () {
 console.log('connection closeed');
})

const r1 = readline.createInterface({
 input: process.stdin,
 output: process.stdout
})

function say() {
 r1.question('請輸入:', (inputMsg) => {
   if (inputMsg != 'bye') {
     socket.write(inputMsg + '\n')
  } else {
     socket.destroy()
     r1.close()
  }
})
}

websocket

const ws = new WebSocket('ws://localhost:8080/')

ws.onopen = () => {
 ws.send('你們好')
}

ws.onmessage = (msg) => {
 const content = document.getElementById('content')
 content.innerHTML += msg.data + '<br/>'
}

ws.onerror = (err) => {
 console.log(err);
}

ws.onclose = () => {
 console.log('closed~');
}
ws.send(msg2)

server.js

const WebSocket = require('ws')
const ws = new WebSocket.Server({ port: 8080 })

let clients = {}
let clientName = 0

ws.on('connection', (client) => {
 client.name = ++clientName
 clients[client.name] = client

 client.on('message', (msg) => {
   broadcast(client, msg)
})

 client.on('close', () => {
   delete clients[client.name]
   console.log(client.name + ' 離開了~')
})
})

function broadcast(client, msg) {
 for (var key in clients) {
   clients[key].send(client.name + ' 說:' + msg)
}
}

項目實戰

api接口

  • RestfulApi 規範

  • 接口文檔的生成(apidoc)

  • 接口請求方式區別

跨域解決

  • cors

  • jsonp

  • proxy

身份驗證

JWT

產生token

var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');

驗證token

// verify a token symmetric
jwt.verify(token, 'shhhhh', function(err, decoded) {
  console.log(decoded.foo) // bar
});

Cookie+Session

npm install express-session -d --save

app.use(session({
  secret: "weird sheep",
  resave: false,
  saveUninitialized: true,
  cookie: {user:"default",maxAge: 14*24*60*60*1000}
}));
session存值
req.session.user = user;
req.session.isLogin = true;

圖片上傳

  1. 安裝multer模塊

npm install multer
  1. 引用模塊它是依賴於express的一個模塊

//引用express並配置
var express = require("express");
var app = express();
app.listen(3000);
var multer = require('multer');
/*var upload = multer({
//若是用這種方法上傳,要手動添加文明名後綴
      //若是用下面配置的代碼,則能夠省略這一句
dest: 'uploads/'
})*/
  1. 配置設置保存文件的地方,並根據上傳的文件名對應文件添加後綴能夠經過filename屬性定製文件保存的格式

屬性值 用途
destination 設置資源的保存路徑。注意,若是沒有這個配置項,默認會保存在/tmp/uploads下。此外,路徑須要本身建立
filename 設置資源保存在本地的文件名
var storage = multer.diskStorage({
//設置上傳後文件路徑,uploads文件夾會自動建立。
destination: function(req, file, cb) {
cb(null, './uploads')
},
//給上傳文件重命名,獲取添加後綴名
filename: function(req, file, cb) {
var fileFormat = (file.originalname).split(".");
//給圖片加上時間戳格式防止重名名
//好比把 abc.jpg圖片切割爲數組[abc,jpg],而後用數組長度-1來獲取後綴名
cb(null, file.fieldname + '-' + Date.now() + "." + fileFormat[fileFormat.length - 1]);
}
});
var upload = multer({
storage: storage
});
  1. 接受文件upload.single('xxx'),xxx與表單中的name屬性的值對應這裏雖然用到post請求,但實際上不須要bodyParser模塊處理

app.post('/upload-single', upload.single('logo'), function(req, res, next) {
console.log(req.file)
console.log('文件類型:%s', req.file.mimetype);
console.log('原始文件名:%s', req.file.originalname);
console.log((req.file.originalname).split("."))
console.log('文件大小:%s', req.file.size);
console.log('文件保存路徑:%s', req.file.path);
res.send({
ret_code: '0'
});
});
  1. 多圖上傳多圖上傳只要更改一下地方,前端往file輸入框加多一個multiple="multiple"屬性值,此時就能夠在選圖的時候多選了,固然也能夠並列多個file輸入框(不推薦多個上傳圖片輸入框),這樣體驗會很差

<input type="file" name="logo" multiple="multiple" />

後端也須要相應的改變

app.post('/upload-single', upload.single('logo'), function(req, res, next) {
//upload.single('logo')變爲upload.array('logo', 2),數字表明能夠接受多少張圖片
app.post('/upload-single', upload.array('logo', 2), function(req, res, next) {

若是不想有圖片數量上傳限制,咱們能夠用upload.any()方法

app.post('/upload-single', upload.any(), function(req, res, next) { 
res.append("Access-Control-Allow-Origin","*");
res.send({
wscats_code: '0'
});
});
  1. 前端部分

  • formData表單提交

<form action="http://localhost:3000/upload-single" method="post" enctype="multipart/form-data">
<h2>單圖上傳</h2>
<input type="file" name="logo">
<input type="submit" value="提交">
</form>
  • formData表單+ajax提交

<form id="uploadForm">
<p>指定文件名: <input type="text" name="filename" value="" /></p>
<p>上傳文件: <input type="file" name="logo" /></ p>
<input type="button" value="上傳" onclick="doUpload()" />
</form>

FormData對象,是可使用一系列的鍵值對來模擬一個完整的表單,而後使用XMLHttpRequest發送這個"表單"

注意點

  • processData設置爲false。由於data值是FormData對象,不須要對數據作處理。

  • <form>標籤添加enctype="multipart/form-data"屬性。

  • cache設置爲false,上傳文件不須要緩存。

  • contentType設置爲false。由於是由<form>表單構造的FormData對象,且已經聲明瞭屬性enctype="multipart/form-data",因此這裏設置爲false

上傳後,服務器端代碼須要使用從查詢參數名爲logo獲取文件輸入流對象,由於<input>中聲明的是name="logo"

function doUpload() {
$.ajax({
url: 'http://localhost:3000/upload-single',
type: 'POST',
cache: false, //沒必要須
data: new FormData($('#uploadForm')[0]),
processData: false,//必須
contentType: false,//必須
success: function(data) {
console.log(data)
}
})
}

參考文檔Github MyDemo       Github Multer        MDN        FormData對象的使用

相關文章
相關標籤/搜索