node 中的事件循环
nodejs 和 浏览器的 eventLoop 还是有很大差别的,值得单独拿出来说一说。
不知你是否看过关于 nodejs 中 eventLoop 的一些文章, 是否被这些流程图搞得眼花缭乱、一头雾水:
看到这你不用紧张,这里会抛开这些晦涩的流程图,以最清晰浅显的方式来一步步拆解 nodejs 的事件循环机制。
1. 三大关键阶段首先,梳理一下 nodejs 三个非常重要的执行阶段:
执行 定时器回调 的阶段。检查定时器,如果到了时间,就执行回调。这些定时器就是setTimeout、setInterval。这个阶段暂且叫它timer。
轮询(英文叫poll)阶段。因为在node代码中难免会有异步操作,比如文件I/O,网络I/O等等,那么当这些异步操作做完了,就会来通知JS主线程,怎么通知呢?就是通过’data’、‘connect’等事件使得事件循环到达 poll 阶段。到达了这个阶段后:
如果当前已经存在定时器,而且有定时器到时间了,拿出来执行,eventLoop 将回到timer阶段。
如果没有定时器, 会去看回调函数队列。
如果队列不为空,拿出队列中的方法依次执行
如果 ...
Vue.js 源码解析: vue 响应式原理
Vue 响应式原理解析大家都知道 vue 是双向数据绑定,vue 的双向数据绑定使用的是 v-model 实现。v-model实际上是 input 的事件 和 value 属性值。其最本质的原理是基于 vue 的响应式原理实现。响应式的实现原理是怎么样的呢?让我们接下来一起看看
1. 数据劫持源码位置:vue/src/core/observer/index.ts在vue 源码有这么一个函数 defineReactive,其本质是使用Object.defineProperty 方法劫持对象属性,使得在访问和修改属性时能够执行特定的操作
get: 用于获取属性值,同时进行依赖收集
set: 设置新值,触发依赖更新。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989 ...
Vue.js 源码解析:深度理解 initProps 函数
Vue.js 源码解析:深度理解 initProps 函数引言在 Vue.js 中,initProps 函数是组件初始化过程中的一个重要步骤,它负责处理组件的 props,使其变成响应式,并提供一些警告和检查。本文将深入解析 initProps 函数,探讨其实现原理和关键步骤。本文基于 Vue 源码 version 2.7.14
背景在开始之前,我们需要了解一些背景知识:
Vue 组件的 props 是用于接收父组件传递的数据机制。
props 同样具有响应式,响应式系统是 Vue 的核心特性之一,它能用追踪数据的变化并实现视图的自动更新。
initProps 函数源码位置:vue/src/core/instance/state.ts
1. initProps 函数的作用initProps 主要用于处理组件的‘props’, 使其成为具有响应式数据,函数的核心功能:
获取props 数据: 从 vm.$options.propsData 获取 props 数据
创建响应式数据: 使用 shallowReactive创建一个浅层的响应式对象,并赋值给 vm._props
切换 ...
http history
HTTP1.0Http1.0 是最早的版本,它使用短链接,每次请求都需等待服务器响应后关闭连接。它最早被使用在1996年的网页,开始人们只使用一些简单的 web 页和网络请求上,在1999年时广泛使用Http1.1
Http1.0 的缺点:
短链接:http1.0 使用的是短链接方式,每个请求都必须建立连接和断开连接,每个连接都需要经过 TCP 连接过程(三次握手四次挥手的过程)
不支持复用header头,每次请求都需要发送完整的请求头信息
不支持对数据进行二进制分帧传输(?)
通过 expires 头来表示资源的过期时间,缺点 如果服务器和客户端的时间不一致,缓存可能会出现问题。
http1.1 没有提供对缓存的有效性验证,每次都需要重新下载整个资源,没有办法优化带宽利用。
不支持加密,所有数据传输都是明文传输,存在安全风险,需要额外使用安全协议(https 来对 http进行数据加密和身份校验)
HTTP1.1在Http1.0 每次连接都需要建立完成的 TCP 连接,所以在 1999年时开始广泛使用Http1.1。它们的主要区别在:
针对http1.0的短链接,http1.1 ...
浏览器的存储
浏览器的本地存储主要分为Cookie、WebStorage和IndexDB, 其中WebStorage又可以分为localStorage和sessionStorage。接下来我们就来一一分析这些本地存储方案。
CookieCookie 最开始被设计出来其实并不是来做本地存储的,而是为了弥补HTTP在状态管理上的不足。
HTTP 协议是一个无状态协议,客户端向服务器发请求,服务器返回响应,故事就这样结束了,但是下次发请求如何让服务端知道客户端是谁呢?
这种背景下,就产生了 Cookie.
Cookie 本质上就是浏览器里面存储的一个很小的文本文件,内部以键值对的方式来存储(在chrome开发者面板的Application这一栏可以看到)。向同一个域名下发送请求,都会携带相同的 Cookie,服务器拿到 Cookie 进行解析,便能拿到客户端的状态。
Cookie 的作用很好理解,就是用来做状态存储的,但它也是有诸多致命的缺陷的:
容量缺陷。Cookie 的体积上限只有4KB,只能用来存储少量的信息。
性能缺陷。Cookie 紧跟域名,不管域名下面的某一个地址需不需要这个 Cookie ...
nodejs中的异步、非阻塞I/O是如何实现的?
在听到 nodejs 相关的特性时,经常会对 异步I/O、非阻塞I/O有所耳闻,听起来好像是差不多的意思,但其实是两码事,下面我们就以原理的角度来剖析一下对 nodejs 来说,这两种技术底层是如何实现的?
什么是I/O?首先,我想有必要把 I/O 的概念解释一下。I/O 即Input/Output, 输入和输出的意思。在浏览器端,只有一种 I/O,那就是利用 Ajax 发送网络请求,然后读取返回的内容,这属于网络I/O。回到 nodejs 中,其实这种的 I/O 的场景就更加广泛了,主要分为两种:
文件 I/O。比如用 fs 模块对文件进行读写操作。
网络 I/O。比如 http 模块发起网络请求。
阻塞和非阻塞I/O阻塞和非阻塞 I/O 其实是针对操作系统内核而言的,而不是 nodejs 本身。阻塞 I/O 的特点就是一定要等到操作系统完成所有操作后才表示调用结束,而非阻塞 I/O 是调用后立马返回,不用等操作系统内核完成操作。
对前者而言,在操作系统进行 I/O 的操作的过程中,我们的应用程序其实是一直处于等待状态的,什么都做不了。那如果换成非阻塞I/O,调用返回后我们的 n ...
forEach 中用 await 会产生什么问题
问题:对于异步代码,forEach 并不能保证按顺序执行。
举个例子:
123456789101112131415161718async function test() { let arr = [4, 2, 1] arr.forEach(async item => { const res = await handle(item) console.log(res) }) console.log('结束')}function handle(x) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(x) }, 1000 * x) })}test()
我们期望的结果是:
12344 2 1结束
但是实际上会输出:
1234结束124
问题原因这是为什么呢?我想我们有必要看看forEach底层怎么实现的。
1234567// 核心逻辑for (var i = ...
forEach 循环
在forEach中用return不会返回,函数会继续执行。
1234let nums = [1, 2, 3];nums.forEach((item, index) => { return;//无效})
中断方法:
使用try监视代码块,在需要中断的地方抛出异常。
官方推荐方法(替换方法):用every和some替代forEach函数。every在碰到return false的时候,中止循环。some在碰到return ture的时候,中止循环
算法:二分查找
二分查找给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
12345678910示例 1:输入: nums = [-1,0,3,5,9,12], target = 9输出: 4解释: 9 出现在 nums 中并且下标为 4示例 2:输入: nums = [-1,0,3,5,9,12], target = 2输出: -1解释: 2 不存在 nums 中因此返回 -1
leetcode链接:二分查找
分析这道题目的前提是数组为有序数组,同时还强调,数组中无重复元素,因为一旦有重复元素,使用二分查找返回的元素下标 可能不是唯一的。
所以使用二分法的前提条件:
有序,2. 数组中无重复值
二分法,掌握二分法的核心就是处理好二分法的边界条件,需要理解区间的定义。
写二分法,区间的定义一般分为两种:左闭右闭 [left,right] 或者 左闭右开 [left,right).
两种区间的定义,分别有两种不同的二分写法
第一种写法,左闭右闭第一种写法,定义 target 是 ...
算法:分发饼⼲
分发饼干假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
1234567891011121314151617示例 1:输入: g = [1,2,3], s = [1,1]输出: 1解释: 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。所以你应该输出1。示例 2:输入: g = [1,2], s = [1,2,3]输出: 2解释: 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。你拥有的饼干数量和尺寸都足以让所有孩子满足。所以你应该输出2.
leetcode链接:https://leetcode.cn/problems/assign-cookies/description/
分 ...