into-piece / Step-By-Step

每天一题向前端架构师前进
4 stars 1 forks source link

20200513 #26

Open into-piece opened 4 years ago

into-piece commented 4 years ago

koa的洋葱模型实现

koa被认为是第二代node web framework,它最大的特点就是独特的中间件流程控制,是一个典型的洋葱模型。koa和koa2中间件的思路是一样的,但是实现方式有所区别,koa2在node7.6之后更是可以直接用async/await来替代generator使用中间件,本文以最后一种情况举例。

const Koa = require('koa');

const app = new Koa();
const PORT = 3000;

// #1
app.use(async (ctx, next)=>{
    console.log(1)
    await next();
    console.log(1)
});
// #2
app.use(async (ctx, next) => {
    console.log(2)
    await next();
    console.log(2)
})

app.use(async (ctx, next) => {
    console.log(3)
})

app.listen(PORT);
console.log(`http://localhost:${PORT}`);

当程序运行到await next()的时候就会暂停当前程序,进入下一个中间件,处理完之后才会仔回过头来继续处理。也就是说,当一个请求进入,#1会被第一个和最后一个经过,#2则是被第二和倒数第二个经过,依次类推。

实现

koa的实现有几个最重要的点

  1. context的保存和传递
  2. 中间件的管理和next的实现

当我们app.use的时候,只是把方法存在了一个数组里。

use(fn) {
    this.middleware.push(fn);
    return this;
}

服务端是如何做路由分发

操作系统 - 磁盘寻道调度算法

FIFO

先入先出队列(First Input First Output,FIFO)这是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令。

先来先服务算法(FCFS)

这是一种比较简单的磁盘调度算法。它根据进程请求访问磁盘的先后次序进行调度。此算法的优点是公平、简单,且每个进程的请求都能依次得到处理,不会出现某一进程的请求长期得不到满足的情况。此算法由于未对寻道进行优化,在对磁盘的访问请求比较多的情况下,此算法将降低设备服务的吞吐量,致使平均寻道时间可能较长,但各进程得到服务的响应时间的变化幅度较小。

最短寻道时间优先算法(SSTF),

该算法选择这样的进程,其要求访问的磁道与当前磁头所在的磁道距离最近,以使每次的寻道时间最短,该算法可以得到比较好的吞吐量,但却不能保证平均寻道时间最短。其缺点是对用户的服务请求的响应机会不是均等的,因而导致响应时间的变化幅度很大。在服务请求很多的情况下,对内外边缘磁道的请求将会无限期的被延迟,有些请求的响应时间将不可预期。

扫描算法(SCAN)(电梯调度算法)

循环扫描算法(CSCAN)

常见进程间通信(IPC)方式

从输入 URL 到页面渲染经历了什么

5个主要步骤

1 DNS 查询 2 TCP 连接 3 HTTP 请求即响应 4 服务器响应 5 客户端渲染

浏览器渲染分五个步骤

  1. 处理 HTML 标记并构建 DOM 树。

  2. 处理 CSS 标记并构建 CSSOM 树。

  3. 将 DOM 与 CSSOM 合并成一个渲染树。

  4. 根据渲染树来布局,以计算每个节点的几何信息。

  5. 将各个节点绘制到屏幕上。

  6. cdn解析:浏览器缓存=》本机缓存

  7. 建立tcp连接: 检查是否强缓存/协商缓存

  8. 请求资源html的解析(词法分析和语法分析

  9. css和js文件的请求和解析

  10. 构建的DOM树和cssom树结合生成render tree

构建对象模型

  1. 转换: 浏览器从磁盘或网络读取 HTML 的原始字节,并根据文件的指定编码(例如 UTF-8)将它们转换成各个字符。
  2. 令牌化: 浏览器将字符串转换成 W3C HTML5 标准规定的各种令牌,例如,“”、“”,以及其他尖括号内的字符串。每个令牌都具有特殊含义和一组规则。
  3. 词法分析: 发出的令牌转换成定义其属性和规则的“对象”。
  4. DOM 构建: 最后,由于 HTML 标记定义不同标记之间的关系(一些标记包含在其他标记内),创建的对象链接在一个树数据结构内,此结构也会捕获原始标记中定义的父项-子项关系:HTML 对象是 body 对象的父项,body 是 paragraph 对象的父项,依此类推。 js执行,会堵塞GUI渲染线程,

渲染层合并

setTimeout setImmediate process.nextTick的区别

链接 Node.js的event loop及timer/setImmediate/nextTick

/process.nextTick

process.nextTick()方法的操作相对较为轻量,每次调用Process.nextTick()方法,只会将回调函数放入队列中,在下一轮Tick时取出执行。定时器采用红黑树的操作时间复杂度为o(lg(n)),而nextTick()的时间复杂度为o(1)。相较之下,process.nextTick()更高效。

setImmediate()方法和process.nextTick()方法十分类似,都是将回调函数延迟在下一次立即执行。

区别 1、process.nextTick中回调函数的优先级高于setImmediate 原因在于事件循环对观察者的检查是有先后顺序的,process.nextTick属于idle观察者,setImmediate属于check观察者。在每一轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者。

多个process.nextTick语句总是一次执行完,多个setImmediate则需要多次才能执行完。

2、在实现上,process.nextTick的回调函数保存在一个数组中,setImmediate则保存在一个链表中

3、setImmediate可以使用clearImmediate清除,process.nextTick不能被清除。

观察者优先级

在每次轮训检查中,各观察者的优先级分别是:

idle观察者 > I/O观察者 > check观察者。

idle观察者:process.nextTick

I/O观察者:一般性的I/O回调,如网络,文件,数据库I/O等

check观察者:setImmediate,setTimeout

setTimeoout和setImmiediate谁快?

在一个异步流程里,setImmediate会比定时器先执行

同样在最外层的,需要看情况。

node.js里面setTimeout(fn, 0)会被强制改为setTimeout(fn, 1)

我们发现关键就在这个1毫秒,如果同步代码执行时间较长,进入Event Loop的时候1毫秒已经过了,setTimeout执行,如果1毫秒还没到,就先执行了setImmediate。每次我们运行脚本时,机器状态可能不一样,导致运行时有1毫秒的差距,一会儿setTimeout先执行,一会儿setImmediate先执行。但是这种情况只会发生在还没进入timers阶段的时候。

http2对比websocket

vue3

性能:

编译模板的优化(PatchFlag:告知我们不光有TEXT变化,还有PROPS变化(id)。这样既跳出了virtual dom性能的瓶颈,又保留了可以手写render的灵活性。 等于是:既有react的灵活性,又有基于模板的性能保证。

事件监听缓存:cacheHandlers

开启cacheHandlers会自动生成并缓存一个内联函数,“神奇”的变为一个静态节点。 Ps:相当于React中useCallback自动化。