这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
书接上回,继续做笔记。
异步编程
JavaScript一般来说是单线程的,一个线程每次只能顺序执行任务。如果当前执行的任务非常耗时,就会导致阻塞。现在可以使用Web workers开一个单独的线程,不过这个worker线程不可以操作DOM,基本只做大量计算的任务。因此异步编程就显得十分重要。
有时候代码执行时需要明确知道前面代码是否执行完成,就必须等待response 返回才能继续往下执行。为了解决这个问题,JavaScript异步编程从callback到promise再到现在的async一路发展。
callback
callback作为函数可以作为参数传递给其他的函数,就比如addEventListener()第二个参数:
btn.addEventListener('click', () => {
alert('You clicked me!');
});
当用户点击按钮,就调用回调函数。 如果回调太多,层层嵌套,就会让代码调试变得困难,因此有了回调地狱的概念。
promise
为了解决回调地狱的问题,引入了promise,promise是一个具有四个状态的有限状态机,其中三个核心状态为pending(挂起),fulfilled(完成),rejected(拒绝),以及还有一个未开始的状态。
每个.then()块返回一个新的promise,最后使用一个.catch()块来处理所有错误
async
async / await是基于promises的语法糖,使异步代码更易于编写和阅读。
在函数声明时加入async,声明这是一个异步函数,返回一个promise。await只在异步函数里面才起作用,await后面的语句会等待promise 完成。
使用try catch 捕获异常,
.catch((e) =>console.log(e)
events
Node.js中内置了一个events模块,可以在其中创建、触发和侦听您自己的事件。
var events = require('events');
var eventEmitter = new events.EventEmitter();
比如HTTP server on('request')事件监听
web应用开发
http模块
node.js内置http模块:
const http = require('http');
http.createServer((req, res) => {
res.end('hello World\n');
}).listen(3000, () => {
console.log('App running at http://127.0.0.1:3000/')
})
这里我用express的方式实现
const express = require("express");
const app = express();
const port = 3000;
app.get('/hello'(req, res) => {
res.send({
data: 'hello'
})
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
Koa
Koa —— 基于Node.js平台的下一代Web开发框架
Koa它不仅仅提供了一个轻量优雅的函数库,使得编写Web应用变得得心应手,不在内核方法中绑定任何中间件。Koa由Express原班人马打造,使用Async/Await,也就是基于Promise重构,更加轻量、快速。
执行过程
- 服务启动
- 实例化application
- 注册中间件
- 创建服务、监听端口
- 接受/处理请求
- 获取请求req、res 对象
- req -> request、res -> response 封装
- request & response -> context
- 执行中间件
- 输出设置到ctx.body 上的内容
中间件
Koa的中间件是洋葱模型
常用中间件
- koa-router:路由解析
- koa-body: request body 解析
- koa-logger:日志记录
- koa-views: 模板渲染
- koa2-cors :跨域处理
- koa-session:session 处理
- koa-helmet:安全防护
- ...
Koa 中间件繁多,质量参差不齐,需要合理选择,高效组合...
有一些基于Koa二次开发的前端框架,比如thinkjs、egg、turbo、era、gulu...
此处有部分开发调试的知识,可以参考我之前的笔记:前端开发调试笔记
线上部署
node.js保持了JavaScript在浏览器中单线程的特点。基于事件驱动、异步非阻塞模式,可以应用于高并发场景,同时避免了线程创建、线程上下文切换所产生的资源开销。
为了利用多核CPU,node可以利用cluster/child_process模块。如下代码所示,OS模块可以检测系统有多少个CPU核,Cluster模块可以创建多个子进程。
const express = require("express")
const os = require("os")
const cluster = require("cluster")
const clusterWorkerSize = os.cpus().length
if (clusterWorkerSize > 1) {
if (cluster.isMaster) {
for (let i=0; i < clusterWorkerSize; i++) {
cluster.fork()
}
}
多进程应对并发更好,使用多进程部署性能更好。比方说node进行复杂会卡cpu,怎么办?这时候就可以使用多进程,把复杂计算单独开个子进程去处理。
同时使用多进程有更好的健壮性,方便进行进程守护,看到一个进程故障退出后立刻fork一个新进程。也可以用进程管理工具,比如nodemon和PM2,PM2用的多一点,这是我在本地运行服务的示例图:
pm2常用命令: