1, 什么是nodejs
官网说:Node.js是一个基于Chrome V8引擎的JavaScript运行环境,
Node.js使用了一个事件驱动,非阻塞式 I/o的模型,使其轻量有高效
认识的真谛要用自己一辈子去理解, Node.js的真谛也是一样,需要你不停的去学习理解
2,node.js和chrome不同?
注意:在Node.js里面运行JavaScript跟在Chrome里运行JavaScript有什么不同?
其实,在Node.js里面写JS和在Chrome里面写JS,几乎没有不一样,不一样的地方在于,Node.js没有浏览器API, 即document, window等, 加入了很多Node.jsAPI, 对开发者来说, 在Chrome里面写JavaScript控制浏览器, 在Node.js里面写JavaScript, 让你控制整个计算机。
- node中常见拥有的API
console.log('Hello World')
console.log(Date)
console.log(Math)
console.log(setTimeout)
console.log(setInterval)
console.log(setImmediate)
// 当前运行的脚本所在的位置
console.log(__filename)
// 当前运行的脚本所在的文件目录
console.log(__dirname)
console.log(process)
3, 石头剪刀布游戏
var playerAction = process.argv[process.argv.length - 1]
console.log('玩家出了:',playerAction)
var random = Math.random() * 3;
if (random < 1) {
var computerAction = 'rock'
} else if (random > 2) {
var computerAction = 'scissor'
} else {
var computerAction = 'paper'
}
console.log('电脑出了:', computerAction)
if (computerAction == playerAction ){
console.log('平局')
} else if (
(computerAction === 'rock' && playerAction === 'paper') ||
(computerAction === 'scissor' && playerAction == 'rock') ||
(computerAction === 'paper' && playerAction === 'scissor')
) {
console.log('你赢了')
} else {
console.log('你输入了')
}
$ node index.js rock
玩家出了: rock
电脑出了: paper
你输入了
4,模块规范
传统JS加载方式,通过<script>脚本,脚本变多的时候,需要手动管理加载顺序, 不同脚本之前的逻辑调用,需要通过全局变量的方式,不方便后续的管理,而且,有的时候,是没有HTML页面的,在JavaScript的社区推广下,CommonJS 模块规范运用而生,也在Node.js上得到广大的推广,慢慢的也影响到了浏览器端的JavaScript。
封装一下:上面的石头剪刀布游戏:
lib.js
module.exports = function (playerAction) {
var random = Math.random() * 3;
if (random < 1) {
var computerAction = "rock";
} else if (random > 2) {
var computerAction = "scissor";
} else {
var computerAction = "paper";
}
console.log("我出了:", computerAction);
if (computerAction == playerAction) {
console.log("平局");
return 0;
} else if (
(computerAction === "rock" && playerAction === "paper") ||
(computerAction === "scissor" && playerAction == "rock") ||
(computerAction === "paper" && playerAction === "scissor")
) {
console.log("你赢了");
return -1;
} else {
console.log("你输入了");
return 1;
}
};
index.js
var playerAction = process.argv[process.argv.length - 1]
const game = require('./lib')
let count = 0;
process.stdin.on('data', e=> {
const playerAction = e.toString().trim();
const result = game(playerAction)
console.log(result)
if (result == -1) {
count++;
}
if (count === 3) {
console.log('你太厉害了,我不玩了')
process.exit()
}
})
5, 非阻塞I/O
注意:对比glob方法,读取目录下的文件,查看耗时
const glob = require('glob')
// 阻塞代码 3248ms
var result = null;
console.time('glob')
result = glob.sync(__dirname + '/**/*')
console.timeEnd('glob')
console.log(result)
// 异步,回调 2ms
console.time('glob-2')
glob(__dirname + '/**/*', function(err, res) {
result = res;
console.log('get result', result)
})
console.timeEnd('glob-2')
6, 异步编程-callback
-
回调函数格式规范
error-first-callback
node-style-callback
-
第一个参数是error, 后面的参数才是结果
interview(function(res) {
if( res instanceof Error) {
return console.log('cry')
}
console.log('smile')
})
function interview(callback) {
setTimeout(() => {
if(Math.random() < 0.8) {
callback('success')
} else {
callback(new Error('fail'))
}
}, 500)
}
异步流程控制:
事件循环:
const eventloop = {
queue : [],
loop() {
while (this.queue.length) {
var callback = this.queue.shift();
callback()
}
setTimeout(this.loop.bind(this), 50)
},
add(callback) {
this.queue.push(callback);
}
}
eventloop.loop()
setTimeout(() => {
eventloop.add(function() {
console.log(1)
})
}, 500)
setTimeout(() => {
eventloop.add(function() {
console.log(2)
})
}, 800)
7, promise
-
当前事件循环得不到的结果,但未来的事件循环会给到你结果
-
是一个状态机
pending fultilled/resolved rejected
.then 和 .catch
1, resolved 状态的promise会调用后面的第一个.then
2, rejected状态的Promise会回调后面的第一个.catch
3, 任何一个rejected状态且后面没有.catch的promise, 都会造成浏览器/node环境的全局错误
var promise = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(3)
}, 500)
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
console.log(promise)
setTimeout(() => {
console.log(promise)
}, 800)
注意:执行then和catch会返回一个新的Promise, 该Promise最终状态根据then和catch的回调函数的执行结果决定
- 如果回调函数最终是throw, 该promise是rejected状态。
- 如果回调函数最终是return, 该promise是resolved状态
- 如果回调函数最终return了一个Promise, 该Promsie会和回调函数return的Promise状态保持一致
;(function() {
var promise = interview(1)
.then(() => {
return interview(2)
})
.then(() => {
return interview(3)
})
.then(() => {
console.log('smile')
})
.catch((err) => {
console.log('cry at ' + err.round + ' round')
})
function interview(round) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.2) {
resolve('success')
} else {
var error = new Error('fail')
error.round = round
reject(error)
}
}, 500)
})
}
})()
Promise.all的演示
// var promise = new Promise(function(resolve, reject) {
// setTimeout(() => {
// resolve(3)
// }, 500)
// }).then(res => {
// console.log(res)
// }).catch(err => {
// console.log(err)
// })
// console.log(promise)
// setTimeout(() => {
// console.log(promise)
// }, 800)
;(function() {
// var promise = interview(1)
// .then(() => {
// return interview(2)
// })
// .then(() => {
// return interview(3)
// })
// .then(() => {
// console.log('smile')
// })
// .catch((err) => {
// console.log('cry at ' + err.round + ' round')
// })
Promise
.all([
interview('geekbang'),
interview('tencent')
])
.then(() => {
console.log('smile')
})
.catch((err) => {
console.log('cry for ' + err.name)
})
function interview(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.2) {
resolve('success')
} else {
var error = new Error('fail')
error.name = name
reject(error)
}
}, 500)
})
}
})()
8, async/await
async function 是Promise的语法糖封装
异步编程的终极方案, 以同步的方式写异步
console.log(async function() {
throw new Error('4')
}())
console.log(function() {
return new Promise((resolve, reject) => {
reject(new Error('4'))
})
}())
- await关键字可以暂停 async function的执行
- await关键字可以以同步的写法获取promise的执行结果
- try-catch可以获取await所得到的错误
;(function() {
const result = async function() {
try {
var content = await new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('8'))
}, 500)
})
} catch(e) {
console.log('err', e.message)
}
console.log(content)
return 4;
}()
setTimeout(() => {
console.log(result)
}, 800)
})()
undefined
VM410:10 err 8
VM410:12 undefined
VM410:16 Promise {<fulfilled>: 4}
注意:对之前的代码进行async/await进行修改
;(async function() {
try {
await interview('1')
await interview('2')
await interview('3')
// 如果想做并行的异步
// await Promise.all([interview(1), interview(2)])
} catch(e) {
return console.log('cry at ' + e.name)
}
console.log('smile')
})()
function interview(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.8) {
resolve('success')
} else {
var error = new Error('fail')
error.name = name
reject(error)
}
}, 500)
})
}