Web 开发 24

1 JavaScript 的 Event Loop(事件循环)

首先,得知道 JavaScript 是单线程的

单线程就是说,同一时间只能做一件事。那如果有特别耗时的操作,比如请求网络数据、等待用户点击按钮,总不能让程序一直卡着吧?所以就得有个机制,让这些耗时操作 "先等着",等准备好了再处理,这时候 Event Loop 就派上用场啦。

然后看 Event Loop 的核心逻辑(就是图里的 while True 部分)

代码里写的是 while True,意思是这个循环会一直运行,不断检查有没有要处理的 "事件" 或者 "Promise 相关的代码"。

  • 先看 if len(events) > 0events 是一个存储 "事件和对应的处理函数" 的队列。如果队列里有事件(长度大于 0),就取出队列最前面的那个事件和它的处理函数(events.pop(0)),然后执行这个处理函数(handler(event))。
  • 再看 const nextCodeToRun = waitingPromises[randomInteger()]; run(nextCodeToRun());waitingPromises 是存储 "Promise 相关待执行代码" 的地方。这里是随机从 waitingPromises 里选一个待执行的代码,然后运行它(run(nextCodeToRun()))。不过实际中,Promise 的执行顺序不是随机的,这里是为了简化讲解~

接下来讲 Promises(承诺 / 期约)

Promise 是用来处理异步操作的。

比如,当我们需要等待一个异步操作(像请求服务器数据)完成,但是在等待的时候又不能让程序卡住,这时候就用 Promise。

  • 图里的注释:"A function promises call when they're waiting for something and can't progress." 翻译过来就是:当一个函数在等待某些东西(比如网络响应),没法继续往下执行的时候,就会用到 Promise。
  • 函数 wait(promise):把传入的 promise 放到 waitingPromises 这个队列里(waitingPromises.push(promise)),然后运行事件循环(runEventLoop())。这一步就是把需要等待的异步任务先存起来,等合适的时候再处理。

再讲 Events(事件)

事件就是当某些特定的事情发生时,要执行的操作。比如用户点击了按钮、页面加载完成等。

  • 图里的注释:"We run this function when events happen!" 意思是当事件发生时,我们运行这个函数。
  • 函数 notifyOfEvent(event, eventHandler):把事件 event 和对应的处理函数 eventHandler 放到 events 队列里(events.push({ event, eventHandler }))。这样,当事件循环运行到检查 events 队列时,就会取出并执行这个事件处理函数。

最后看那两行关键的话

"它们像是两个独立的队列,一个用于承诺,一个用于事件"。

也就是说,waitingPromises 是专门存 Promise 相关待执行代码的队列,events 是专门存事件和对应处理函数的队列。

事件循环会不断地去检查这两个队列,有内容就拿出来执行,这样就实现了在单线程下处理异步操作和事件的能力。

总结一下,Event Loop 就像一个勤劳的小管家,不停地看有没有 "事件" 或者 "Promise 任务" 要处理,有的话就安排执行,这样 JavaScript 虽然是单线程,但也能很好地处理各种异步的情况了。

这张图讲的是 JavaScript 里的 Event Loop(事件循环),它是 JavaScript 处理各种操作(像按钮点击、输入这些)的核心机制。下面分两部分解释:

左边:Synchronous functions(同步函数)

同步函数就像图里带 "STOP" 标志的循环。

  • 同步函数的特点是 "阻塞式" ,就是说,代码会 从上到下依次执行,如果一个同步函数在运行,后面的代码必须等它执行完才能继续。
  • 举个例子:你写了一段代码,先执行 console.log("第一步"),再执行 console.log("第二步"),那肯定是先打印 "第一步",再打印 "第二步",中间不会插其他操作。要是有个同步函数特别耗时(比如复杂的循环计算),那整个程序就会 "卡住",直到它执行完。

右边:Asynchronous functions(异步函数)

异步函数就像图里没有 "STOP"、还能分支出去的循环。

  • 异步函数的特点是 "非阻塞式" ,当遇到异步操作(比如发送网络请求、设置定时器、监听按钮点击)时,JavaScript 不会干等着,而是会继续执行后面的代码。等异步操作完成了,再通过 Event Loop 来处理这个异步操作的结果。
  • 举个例子:你设置了一个定时器 setTimeout(() => console.log("两秒后"), 2000),然后接着写 console.log("现在")。这时候,"现在" 会立刻打印,而 "两秒后" 会等定时器到时间后,由 Event Loop 安排执行。

总结 Event Loop 的作用

Event Loop 就像一个 "调度员",它会不断检查:

  • 同步代码:按顺序执行,执行完一个再下一个。
  • 异步操作:等异步操作(比如定时器到时间、网络请求返回数据)完成后,把对应的回调函数(比如定时器里的 () => console.log("两秒后"))放到 "任务队列" 里,然后 Event Loop 会在同步代码都执行完后,从任务队列里取出回调函数执行。

这样就保证了 JavaScript 虽然是单线程(同一时间只能做一件事),但能高效处理各种操作,不会因为一个耗时的异步操作就卡住整个程序。

2 JavaScript 中 asyncawait 相关知识的总结

  • 使用 await 关键字来等待 Promise 解析完成。
  • 使用 async 关键字来定义异步函数。
  • 必须将每个 await 包裹在 async 函数内部。
  • 任何用 Promise 实现的功能都可以用 async/await 语法重写 ------ 根据具体任务选用最适合的方式即可。

当我们不知道某件事会花费多长时间时,使用 async(异步),比如:

  • 客户端与服务器之间的通信(比如网页向服务器请求数据,不知道网络传输等要多久)。
  • 服务器与数据库之间的通信(服务器从数据库取数据,不确定数据库操作耗时)。
  • React 前端相关操作(前端处理一些可能耗时的交互、数据获取等)。
  • 后台任务(程序在后台执行的、耗时不确定的任务)。

并且提到,这样做能让程序保持响应性,同时也能关注其他操作的进行,不用在之后去等待它(指异步操作)。

3 git stash 相关的工作流程

要理解 git stash 相关的工作流程,咱们可以把它想象成 "临时存放代码改动的小仓库",下面一步步详细解释,还会做些扩展。

1. git stash:把当前改动 "藏" 起来

当你在一个分支(比如 feature 分支)上做了一些代码修改,但还没完成,也没提交(git commit ),这时候你需要去处理其他事,比如切换到 main 分支拉取最新代码(git pull),或者去另一个分支修复 bug。

可如果直接切换分支,Git 会因为有未提交的改动而不让你顺利切换(除非强制,但容易出问题)

这时候就用 git stash

  • 它的作用是:把你当前工作目录里**还没保存(未 git add)、未提交(未 git commit)**的所有代码改动,临时存到 Git 的 "stash 栈" 里,然后把工作目录恢复到 "干净" 的状态(就像你没做这些改动之前的样子)。
  • 举个例子:你在 feature-login 分支改了登录页面的样式和逻辑,改到一半,领导说要紧急修复 main 分支的一个 bug。你就可以 git stash,把这些未完成的登录相关改动藏起来,这样工作目录就干净了,能顺利切换到 main 分支去修 bug。

2. "Do anything":自由进行其他操作

这一步就是说,现在工作目录是干净的了,你可以随便做你需要的操作:

  • 切换分支(git checkout :比如切换到 main 分支、bugfix 分支都可以。
  • 拉取远程代码(git pull :在当前分支获取远程仓库的最新代码。
  • 提交代码、创建分支:甚至可以在当前分支提交已经完成的工作,或者创建新的分支,都不会受到之前 "未提交改动" 的干扰。
  • 扩展:其实不止这些,像执行 git merge(合并分支)、git rebase(变基,整理提交历史)等操作,也可以在这一步进行,因为工作目录是干净的,不会有冲突风险。

3. git stash pop:把藏起来的改动 "取" 回来

等你把其他事情做完了,比如在 main 分支修完 bug 并提交了,现在想回到之前的 feature-login 分支继续开发。这时候就用 git stash pop

  • 它的作用是:从 "stash 栈" 的顶部(因为 git stash 可以多次执行,每次的改动会像叠罗汉一样存在栈里)取出最上面那次 stash 的改动,把这些改动重新应用到当前的工作目录里。同时,会把这次 stash 的记录从 "stash 栈" 里移除(相当于 "取出并删除")。
  • 对应图里的文字:"所有未保存、未提交的本地更改都会重新回到(工作目录的)最上层"。比如你之前藏起来的登录页面改动,现在就会重新出现在工作目录里,你可以接着之前的进度继续开发。
  • 扩展:如果 stash 栈里有多个 stash 记录(比如你多次 git stash 了不同的改动),想指定恢复某一个,可以用**git stash apply stash@{n}n 是 stash 的序号,比如 stash@{0} 是最近一次,stash@{1} 是上一次,以此类推)** 。这种方式不会删除 stash 记录,要是想删除,可以用 git stash drop stash@{n};如果想一次性清空所有 stash 记录,用 git stash clear

额外扩展:git stash 的其他常用命令

  • git stash list:查看 stash 栈里都存了哪些 stash 记录。执行后会列出类似 stash@{0}: WIP on feature-login: abc1234... 改动相关的描述 这样的内容,能清楚看到每次 stash 的信息。
  • git stash save "描述信息":和 git stash 类似,但可以给这次 stash 加一个自定义的描述,方便后续通过 git stash list 识别。比如 git stash save "login page style changes",这样列表里就会显示这个描述,知道这次 stash 存的是登录页面样式的改动。

简单总结整个工作流程:临时藏起未完成的改动 → 自由处理其他分支 / 操作 → 把藏的改动取回来继续开发git stash 就是为了解决 "未完成改动时需要切换分支或做其他操作" 的场景,让代码管理更灵活。

4 Git相关术语和工作流程

一、Terminology(术语)

1. Staging(暂存)
  • 解释:"暂存" 是 Git 里很关键的一步。当你修改了文件后,需要先把这些修改放到 "暂存区",这一步是在告诉 Git:"我准备把这些文件的改动提交(git commit)了"。
  • 举例:比如你改了 index.jsstyle.css 两个文件,用 git add index.js git add style.css,就是把这两个文件的改动放到暂存区,标记为 "要提交的改动"。如果不暂存,直接 git commit 的话,Git 不会把未暂存的改动包含到提交里。
2. Commit(提交)
  • 解释:提交可以理解为 "把暂存区里的改动,保存成一个版本快照"。每个提交都对应一个特定的任务(比如 "修复登录页 bug""添加用户注册功能"),并且会有一个唯一的哈希值(像一串乱码的字符,比如 a1b2c3d),方便追踪版本。
  • 举例:你完成了登录功能的代码编写,把相关文件暂存后,执行 git commit -m "完成登录功能开发",这就生成了一个提交,里面包含了这次关于登录功能的所有代码改动。之后如果代码出问题,还能通过这个提交的哈希值回退到这个版本。
3. Branch(分支)
  • 解释:分支就像 "代码仓库的分叉路线"。默认情况下,Git 会有一个 main(或以前的 master)分支,作为主分支。**当你要开发新功能或者修复 bug 时,创建一个新分支(比如 feature-userbugfix-login),这样新分支的提交历史就会和主分支 "分叉" 开。**目的是把相关的提交(比如某个功能的所有开发提交)分组,方便管理,也避免直接在主分支上改代码带来的风险。
  • 举例:要开发用户管理功能,就**git checkout -b feature-user 创建并切换到 feature-user 分支。** 在这个分支上做的所有提交,都属于 "用户管理功能" 相关,等功能开发完,再把这个分支合并(git merge)到 main 分支。
4. Remote/Origin(远程仓库 / 源)
  • 解释:Remote 指的是 "远程的 Git 仓库",通常是存放在互联网上的(比如 GitHub、GitLab 这些平台上的仓库)。Origin 是默认的远程仓库别名,当你用 git clone 从远程仓库克隆代码到本地时,Git 会自动把远程仓库命名为 origin
  • 举例:你在 GitHub 上创建了一个仓库 my-project,然后 git clone https://github.com/yourname/my-project.git 到本地,本地仓库的 origin 就指向 GitHub 上的这个远程仓库。之后你可以通过 git push origin main 把本地 main 分支的代码推送到远程 originmain 分支。
5. Upstream(上游分支)
  • 解释:上游分支是 "本地分支对应的远程分支",也叫 "跟踪分支(tracking branch)"。 当你把本地分支和远程分支关联后,就可以更方便地执行 git pull(拉取远程分支代码到本地)和 git push(推送本地分支代码到远程),因为 Git 知道本地分支对应的远程分支是哪个。
  • 举例:你在本地创建了 feature-user 分支,然后执行 git push -u origin feature-user,这里的 -u 就是把本地 feature-user 分支的上游分支设置为远程 originfeature-user 分支。之后再执行 git pullgit push 时,不用再指定远程仓库和分支,直接 git pullgit push 就行,Git 会自动和上游分支交互。

二、General Workflows(通用工作流程)

1. Create new local branch(创建新的本地分支)
  • 解释:这是开发新功能或修复 bug 的第一步,创建一个独立的本地分支,和主分支隔离,避免影响主分支的稳定。
  • 命令:git checkout -b 分支名(比如 git checkout -b feature-comment,创建并切换到 feature-comment 分支)。这样你就在新分支上工作了,主分支的代码不会受到这个分支改动的影响,除非后续合并。
2. Set upstream (Create corresponding remote branch)(设置上游分支,创建对应的远程分支)
  • 解释:当你在本地创建了新分支,需要把它推送到远程仓库,让团队里的其他人也能看到或协作。第一次推送时,用 -u 参数,既会把本地分支推送到远程,也会设置上游分支关系。
  • 命令:git push -u origin 本地分支名(比如 git push -u origin feature-comment)。执行后,远程仓库(origin)会创建一个和本地分支同名的远程分支,同时本地分支的上游分支就设置为这个远程分支了。
3. Create commits, pull & push often(创建提交,经常拉取和推送)
  • 解释:在分支开发过程中,要频繁地提交代码(把完成的小功能或修复的小 bug 做成提交),这样能保留代码的历史记录,方便回退。同时,经常执行 git pull(拉取远程分支的最新代码,避免和队友的代码冲突)和 git push(把本地提交推送到远程,备份代码,也让队友能看到你的进度)。
  • 举例:在 feature-comment 分支,你完成了评论组件的一部分代码,就 git add .(暂存所有改动),git commit -m "完成评论组件的模板部分",然后 git pull(看看远程有没有新提交,有的话合并过来),再 git push(把自己的提交推到远程)。
4. Merge into main (either directly or Pull Request)(合并到主分支,直接合并或通过拉取请求)
  • 解释:当分支上的功能开发完成,经过测试没问题后,需要把这个分支的代码合并到 main 分支,让主分支包含新功能。
    • 直接合并 :如果是小团队或者个人项目,可以在本地切换到 main 分支,然后 git merge 功能分支名(比如 git merge feature-comment),解决可能的冲突后,再 git push origin main 推送到远程主分支。
    • Pull Request(PR,拉取请求):在团队协作中更常用。你把功能分支推送到远程后,在 GitHub、GitLab 等平台上,发起一个 "拉取请求",告诉团队里的人 "我要把这个分支合并到主分支啦"。队友可以在平台上查看你的代码改动,提出评论或建议,确认没问题后,再由有权限的人合并到主分支。这样能保证代码质量,多人协作更规范。
相关推荐
小小前端_我自坚强3 小时前
前端算法相关详解
前端·算法
小小前端_我自坚强3 小时前
UniApp 微信小程序流水线发布全流程
前端·架构
小小前端_我自坚强3 小时前
vue提高技术 高级语法相关
前端·vue.js·前端框架
小小前端_我自坚强3 小时前
2025年前端最新技术总结
前端·架构
银安3 小时前
Git篇(4):分支(Branch)与引用(Reference)
git
ttyyttemo3 小时前
Text的各种属性
前端
代码守护者3 小时前
React为什么要使用函数式组件代替类组件?一文弄懂函数式组件的优势!
前端
小小前端_我自坚强3 小时前
Vue 3 使用心得
前端·javascript·vue.js
GBVFtou3 小时前
浏览器嵌套兼容处理
前端