-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
218 lines (107 loc) · 77.7 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Hexo</title>
<subtitle>一个程序员的博客</subtitle>
<link href="https://brotaone.github.io/atom.xml" rel="self"/>
<link href="https://brotaone.github.io/"/>
<updated>2025-03-04T09:05:17.299Z</updated>
<id>https://brotaone.github.io/</id>
<author>
<name>Brota Gong</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>Gerrit Code Review</title>
<link href="https://brotaone.github.io/2025/02/28/Gerrit%20Code%20Review/"/>
<id>https://brotaone.github.io/2025/02/28/Gerrit%20Code%20Review/</id>
<published>2025-02-28T09:17:17.000Z</published>
<updated>2025-03-04T09:05:17.299Z</updated>
<content type="html"><![CDATA[<h2 id="Gerrit-Code-Review"><a href="#Gerrit-Code-Review" class="headerlink" title="Gerrit Code Review"></a>Gerrit Code Review</h2><p>在公司平常使用 Gerrit 代码审核方式,平常提交代码需要分为两步</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git commit -m <span class="string">"msg"</span></span><br><span class="line">git push origin HEAD:refs/for/<span class="variable">${branch}</span></span><br></pre></td></tr></table></figure><p>每次都要打一串代码比较麻烦,比 git push 长了很多,有没有办法简化呢?答案是有的,通过 shell 的 alias 将一个复杂的 shell 函数对应到一个简单的命令上,比如 <code>gcmit "这是我的提交信息"</code>,一次就解决了 git commit 和 push 两条命令</p><p>同样的方式也可以单独搞一个 git push 的简化版,不过我比较懒就这样吧</p><h2 id="函数说明"><a href="#函数说明" class="headerlink" title="函数说明"></a>函数说明</h2><p>这个函数分了以下几步</p><ul><li>首先检查是否提供了提交信息。</li><li>使用提供的消息执行 git commit 命令。</li><li>是否提供了分支名,如果没有就获取当前分支名称。</li><li>使用分支名称执行 git push,将提交推送到 Gerrit 代码审查系统的 refs/for/branch_name 引用。</li></ul><h2 id="简化提交代码"><a href="#简化提交代码" class="headerlink" title="简化提交代码"></a>简化提交代码</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">gcmit</span></span>() {</span><br><span class="line"> <span class="comment"># 检查是否有提交信息作为第一个参数传递</span></span><br><span class="line"> <span class="keyword">if</span> [ -z <span class="string">"<span class="variable">$1</span>"</span> ]; <span class="keyword">then</span></span><br><span class="line"> <span class="built_in">echo</span> <span class="string">"Error: Commit message is required."</span></span><br><span class="line"> <span class="built_in">return</span> 1</span><br><span class="line"> <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 第二个参数,如果提供,则使用该分支名称</span></span><br><span class="line"> <span class="built_in">local</span> target_branch=<span class="string">"<span class="variable">$2</span>"</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 如果没有提供第二个参数,则获取当前分支名称</span></span><br><span class="line"> <span class="keyword">if</span> [ -z <span class="string">"<span class="variable">$target_branch</span>"</span> ]; <span class="keyword">then</span></span><br><span class="line"> target_branch=$(git rev-parse --abbrev-ref HEAD)</span><br><span class="line"> </span><br><span class="line"> <span class="comment"># 检查是否成功获取分支名称</span></span><br><span class="line"> <span class="keyword">if</span> [ -z <span class="string">"<span class="variable">$target_branch</span>"</span> ]; <span class="keyword">then</span></span><br><span class="line"> <span class="built_in">echo</span> <span class="string">"Error: Failed to get current branch name."</span></span><br><span class="line"> <span class="built_in">return</span> 1</span><br><span class="line"> <span class="keyword">fi</span></span><br><span class="line"> <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 执行 git commit</span></span><br><span class="line"> git commit -m <span class="string">"<span class="variable">$1</span>"</span></span><br><span class="line"> </span><br><span class="line"> <span class="comment"># 检查 git commit 是否成功</span></span><br><span class="line"> <span class="keyword">if</span> [ $? -ne 0 ]; <span class="keyword">then</span></span><br><span class="line"> <span class="built_in">echo</span> <span class="string">"Error: Git commit failed."</span></span><br><span class="line"> <span class="built_in">return</span> 1</span><br><span class="line"> <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 执行 git push</span></span><br><span class="line"> git push origin HEAD:refs/for/<span class="variable">$target_branch</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">alias</span> gcmit=gcmit</span><br></pre></td></tr></table></figure><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>将下面的函数保存在 shell 配置文件末尾,然后重新加载配置文件,例如运行 source ~/.bashrc 或者 source ~/.zshrc,或者简单地关闭并重新打开终端,就可以了</p>]]></content>
<summary type="html"><h2 id="Gerrit-Code-Review"><a href="#Gerrit-Code-Review" class="headerlink" title="Gerrit Code Review"></a>Gerrit Code Review</h2><p>在公司平常使</summary>
<category term="编程" scheme="https://brotaone.github.io/tags/%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>hexo如何在push时自动部署到github</title>
<link href="https://brotaone.github.io/2024/11/15/hexo%E5%A6%82%E4%BD%95%E5%9C%A8push%E6%97%B6%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/"/>
<id>https://brotaone.github.io/2024/11/15/hexo%E5%A6%82%E4%BD%95%E5%9C%A8push%E6%97%B6%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/</id>
<published>2024-11-15T07:58:36.000Z</published>
<updated>2025-03-04T09:05:17.299Z</updated>
<content type="html"><![CDATA[<h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><p>传统的 hexo 部署到 github 时,需要一个专门的仓库存放静态文件,但是现在 github 提供了 actions 功能,可以直接用来编译、存放静态文件,只需要一个仓库存放 hexo 代码库就可以了</p><h1 id="不足"><a href="#不足" class="headerlink" title="不足"></a>不足</h1><p>因为 github 要求个人版如果想要使用 pages 就必须将对应的仓库公开,传统的 hexo 部署时只需要公开静态文件就可以了,但是这种方法源码也要公开,否则不能使用 pages</p><h1 id="好处"><a href="#好处" class="headerlink" title="好处"></a>好处</h1><p>写完直接 push 就可以了,然后就等 github 为你编译、上传文件了</p><h1 id="创建-hexo-代码库"><a href="#创建-hexo-代码库" class="headerlink" title="创建 hexo 代码库"></a>创建 hexo 代码库</h1><h1 id="新建-actions"><a href="#新建-actions" class="headerlink" title="新建 actions"></a>新建 actions</h1>]]></content>
<summary type="html"><h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><p>传统的 hexo 部署到 github 时,需要一个专门的仓库存放静态文件,但是现在 github 提供了 actions 功能,可以直接用</summary>
<category term="博客" scheme="https://brotaone.github.io/categories/%E5%8D%9A%E5%AE%A2/"/>
<category term="hexo" scheme="https://brotaone.github.io/tags/hexo/"/>
<category term="github" scheme="https://brotaone.github.io/tags/github/"/>
<category term="自动部署" scheme="https://brotaone.github.io/tags/%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/"/>
<category term="博客" scheme="https://brotaone.github.io/tags/%E5%8D%9A%E5%AE%A2/"/>
</entry>
<entry>
<title>JS 多线程脚本</title>
<link href="https://brotaone.github.io/2024/10/21/JS%E5%A4%9A%E7%BA%BF%E7%A8%8B%E8%84%9A%E6%9C%AC/"/>
<id>https://brotaone.github.io/2024/10/21/JS%E5%A4%9A%E7%BA%BF%E7%A8%8B%E8%84%9A%E6%9C%AC/</id>
<published>2024-10-21T09:08:17.000Z</published>
<updated>2025-03-04T09:05:17.299Z</updated>
<content type="html"><![CDATA[<h2 id="脚本意义"><a href="#脚本意义" class="headerlink" title="脚本意义"></a>脚本意义</h2><p>在一个组件库的项目中,因为支持单独安装每个组件,因此目录下有多个 package,所以在升级依赖的时候有些重复的操作,如果一个个改太浪费时间了,即使使用<code>lerna run --stream --sort</code> 这种形式,也可能因为一个 package 运行报错导致全部停止,而且第二次运行的时候又得重头来,还是比较浪费时间的</p><p>于是就自己写了个脚本,可以多进程同时在多个目录下运行,pnpm 下的命令(当然换成shell也是可以的)</p><h2 id="todo"><a href="#todo" class="headerlink" title="todo"></a>todo</h2><p>写的时间有点久,有些地方没有写好,比如没有补上 error 的打印,以及下次还是重头来,如果增加每次检查是否有进度文件,等下次用到的时候再优化下。</p><p>源码一可以在一个文件里就把主、从进程的逻辑写完,源码二就得单独写个文件了,不过源码一也是比较久之前的代码了,还是以 node 服务为例,</p><h2 id="源码一"><a href="#源码一" class="headerlink" title="源码一"></a>源码一</h2><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> cluster <span class="keyword">from</span> <span class="string">'cluster'</span>;</span><br><span class="line"><span class="keyword">import</span> os <span class="keyword">from</span> <span class="string">'os'</span>;</span><br><span class="line"><span class="keyword">if</span> (cluster.<span class="property">isMaster</span>) {</span><br><span class="line"> <span class="keyword">const</span> numCPUs = os.<span class="title function_">cpus</span>().<span class="property">length</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < numCPUs; i++) {</span><br><span class="line"> cluster.<span class="title function_">fork</span>(); <span class="comment">// 创建工作进程</span></span><br><span class="line"> }</span><br><span class="line"> cluster.<span class="title function_">on</span>(<span class="string">'exit'</span>, <span class="function">(<span class="params">worker, code, signal</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Worker</span> ${*worker*.<span class="property">process</span>.<span class="property">pid</span>} died);</span><br><span class="line"> });</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> http.<span class="title function_">createServer</span>(<span class="function">(<span class="params">req, res</span>) =></span> {</span><br><span class="line"> res.<span class="title function_">writeHead</span>(<span class="number">200</span>);</span><br><span class="line"> res.<span class="title function_">end</span>(<span class="string">'Hello World\n'</span>);</span><br><span class="line"> }).<span class="title function_">listen</span>(<span class="number">8000</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="源码二"><a href="#源码二" class="headerlink" title="源码二"></a>源码二</h2><figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { <span class="title class_">Worker</span>, isMainThread, parentPort, workerData } <span class="keyword">from</span> <span class="string">'worker_threads'</span>;</span><br><span class="line"><span class="keyword">import</span> fs <span class="keyword">from</span> <span class="string">'fs'</span>;</span><br><span class="line"><span class="keyword">import</span> { execSync } <span class="keyword">from</span> <span class="string">'child_process'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="variable constant_">PATH</span> = <span class="string">'./packages'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">clusterDo</span> = (<span class="params"></span>) => {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="title function_">execSync</span>(<span class="string">'pnpm lint --fix'</span>, {</span><br><span class="line"> <span class="attr">cwd</span>: workerData.<span class="property">path</span>,</span><br><span class="line"> });</span><br><span class="line"> parentPort.<span class="title function_">postMessage</span>(workerData.<span class="property">path</span> + <span class="string">': success'</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (e) {</span><br><span class="line"> parentPort.<span class="title function_">postMessage</span>(workerData.<span class="property">path</span> + <span class="string">': failed'</span>);</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">handleMessage</span> = (<span class="params">fn, errors</span>) => <span class="function">(<span class="params">path</span>) =></span> {</span><br><span class="line"> <span class="keyword">const</span> name = path?.<span class="title function_">split</span>(<span class="string">':'</span>);</span><br><span class="line"> <span class="keyword">if</span> (name?.[<span class="number">1</span>]?.<span class="title function_">includes</span>(<span class="string">'failed'</span>)) {</span><br><span class="line"> errors.<span class="title function_">push</span>(name?.[<span class="number">0</span>]);</span><br><span class="line"> }</span><br><span class="line"> <span class="title function_">fn</span>();</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">doNext</span> = (<span class="params">countOne, cutOne, errors, getIdx, names, getNum, <span class="keyword">type</span></span>) => {</span><br><span class="line"> <span class="keyword">const</span> idx = <span class="title function_">getIdx</span>();</span><br><span class="line"> <span class="keyword">const</span> num = <span class="title function_">getNum</span>();</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'num: '</span>, num, idx, <span class="keyword">type</span>);</span><br><span class="line"> <span class="keyword">if</span> (idx >= names.<span class="property">length</span>) {</span><br><span class="line"> <span class="keyword">if</span> (num === <span class="number">0</span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'errors: '</span>, errors);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">const</span> worker = <span class="keyword">new</span> <span class="title class_">Worker</span>(<span class="string">'./do.mjs'</span>, {</span><br><span class="line"> <span class="attr">workerData</span>: {</span><br><span class="line"> <span class="attr">path</span>: <span class="string">`<span class="subst">${PATH}</span>/<span class="subst">${names[idx]}</span>`</span>,</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="title function_">countOne</span>(<span class="keyword">type</span>);</span><br><span class="line"></span><br><span class="line"> worker.<span class="title function_">on</span>(</span><br><span class="line"> <span class="string">'message'</span>,</span><br><span class="line"> <span class="title function_">handleMessage</span>(<span class="function">() =></span> <span class="title function_">doNext</span>(countOne, cutOne, errors, getIdx, names, getNum), errors)</span><br><span class="line"> );</span><br><span class="line"> worker.<span class="title function_">on</span>(<span class="string">'error'</span>, doNext);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">mainDo</span> = (<span class="params"></span>) => {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable constant_">MAX_THREAD</span> = <span class="number">15</span>;</span><br><span class="line"> <span class="keyword">const</span> names = fs.<span class="title function_">readdirSync</span>(<span class="variable constant_">PATH</span>);</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'Main thread starting...'</span>, names);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> idx = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">let</span> num = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">const</span> errors = [];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> <span class="title function_">countOne</span> = <span class="keyword">type</span> => {</span><br><span class="line"> idx++;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">type</span> === <span class="string">'new'</span>) {</span><br><span class="line"> num++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> <span class="title function_">cutOne</span> = (<span class="params"></span>) => {</span><br><span class="line"> num--;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> <span class="title function_">getNum</span> = (<span class="params"></span>) => num;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> <span class="title function_">getIdx</span> = (<span class="params"></span>) => idx;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (idx < <span class="variable constant_">MAX_THREAD</span>) {</span><br><span class="line"> <span class="title function_">doNext</span>(countOne, cutOne, errors, getIdx, names, getNum, <span class="string">'new'</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">main</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">if</span> (isMainThread) {</span><br><span class="line"> <span class="title function_">mainDo</span>();</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="title function_">clusterDo</span>();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="title function_">main</span>();</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="脚本意义"><a href="#脚本意义" class="headerlink" title="脚本意义"></a>脚本意义</h2><p>在一个组件库的项目中,因为支持单独安装每个组件,因此目录下有多个 package,所以在升级依赖的时候有些重复的操作,如果一</summary>
<category term="编程" scheme="https://brotaone.github.io/tags/%E7%BC%96%E7%A8%8B/"/>
<category term="前端" scheme="https://brotaone.github.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>React Scheduler 学习</title>
<link href="https://brotaone.github.io/2023/12/25/Scheduler/"/>
<id>https://brotaone.github.io/2023/12/25/Scheduler/</id>
<published>2023-12-25T06:11:17.000Z</published>
<updated>2025-03-04T09:05:17.299Z</updated>
<content type="html"><"></a></h3><p>任务声明(以摸鱼为例)</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> defaultState = { </span><br><span class="line"> <span class="attr">name</span>: <span class="string">'摸鱼'</span>, </span><br><span class="line"> <span class="attr">duration</span>: maxSigned31BitInt, </span><br><span class="line"> <span class="attr">priority</span>: <span class="title class_">LowPriority</span> </span><br><span class="line">};</span><br></pre></td></tr></table></figure><h3 id="2、运行介绍"><a href="#2、运行介绍" class="headerlink" title="2、运行介绍"></a>2、运行介绍</h3><p>每个任务第一次运行时,会记录当下的时间,之后每次运行都会比较两次的运行时间差,计算剩余时间(因为 <code>scheduler</code> 调度不是延时器,无法直接控制两次运行之间的时间差,因为计算差值,会导致哈任务无法暂停,即使因为高优先级任务不断执行,低优先级任务无法执行,过去的时间也无法重新计算)。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">work</span> = (<span class="params"><span class="attr">state</span>: <span class="title class_">State</span></span>) => { </span><br><span class="line"> <span class="keyword">if</span> (!state.<span class="property">startTime</span>) {</span><br><span class="line"> state.<span class="property">startTime</span> = <span class="title class_">Date</span>.<span class="title function_">now</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">const</span> startTime = <span class="title class_">Date</span>.<span class="title function_">now</span>()</span><br><span class="line"> <span class="keyword">const</span> leftTime = (state.<span class="property">startTime</span> - startTime) / <span class="number">1000</span> + state.<span class="property">duration</span>;</span><br><span class="line"> <span class="keyword">const</span> unfinished = leftTime > <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">const</span> newState = unfinished</span><br><span class="line"> ? {</span><br><span class="line"> ...state,</span><br><span class="line"> leftTime,</span><br><span class="line"> }</span><br><span class="line"> : defaultState;</span><br><span class="line"> <span class="title function_">changeState</span>(newState);</span><br><span class="line"> <span class="keyword">return</span> newState;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在 <code>changeState</code> 中会根据 <code>state</code> 更新视图,关键的执行部分就是按钮绑定的 onclick 事件,在 <code>beginWork</code> 中判断了是否是同步任务,是否有剩余时间, <code>scheduleCallback</code> 调度的任务可以返回一个任务,并且会继承原先的任务(由于考虑所有的任务执行完成后,自动恢复成摸鱼任务,如果直接返回的话,那摸鱼任务优先级就会变高了)</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">beginWork</span> = (<span class="params"><span class="attr">state</span>: <span class="title class_">State</span>, <span class="attr">didTimeout</span>?: <span class="built_in">boolean</span></span>) => {</span><br><span class="line"> <span class="keyword">const</span> needSync = state.<span class="property">priority</span> === <span class="title class_">ImmediatePriority</span> || didTimeout;</span><br><span class="line"> <span class="keyword">let</span> <span class="attr">newState</span>: <span class="title class_">State</span> = state;</span><br><span class="line"> <span class="keyword">while</span> (newState.<span class="property">name</span> === state.<span class="property">name</span> && (needSync || !<span class="title function_">shouldYield</span>())) {</span><br><span class="line"> newState = <span class="title function_">work</span>(newState);</span><br><span class="line"> }</span><br><span class="line"> <span class="title function_">scheduleCallback</span>(newState.<span class="property">priority</span>, beginWork.<span class="title function_">bind</span>(<span class="literal">null</span>, newState))</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="高优先级-feature"><a href="#高优先级-feature" class="headerlink" title="高优先级 feature"></a>高优先级 feature</h4><p>由于任务执行时,会判断是否时同步任务,同步任务会不断 while 循环,导致渲染线程无法获得执行时机,页面卡断,无法渲然页面(上厕所就是 <code>ImmediatePriority</code> 任务,运行时页面不会更新试图)。</p><h2 id="三、源码阅读"><a href="#三、源码阅读" class="headerlink" title="三、源码阅读"></a>三、源码阅读</h2><h3 id="1、运行流程"><a href="#1、运行流程" class="headerlink" title="1、运行流程"></a>1、运行流程</h3><p><code>scheduler</code> 维护了 <code>timerQueue</code> 和 <code>taskQueue</code>(均为最小堆,便于获取优先级最高的任务),当 <code>taskQueue</code> 不为空时,会取出任务执行,执行过程中会判断是否需要继续</p><p>当 <code>taskQueue</code> 为空时,会判断 <code>timerQueue</code> 是否为空</p><p>如果要增加任务,需要调 <code>scheduleCallback(priority, callback(didTimeout));</code></p><p><img src="/./Scheduler.assets/33a4277bd7734ea7a272335bd1e66d82.png"></p><ol><li>通过 scheduleCallback 调度新的 callback<ol><li>存在 delay,放入 timerQueue<ol><li>如果 taskQueue 为空,同时 callback 是开始时间最早的 任务<ol><li>取消之前的 timer 回调,并且创建新的</li></ol></li></ol></li><li>不存在 delay,放入 taskQueue<ol><li>如果没有 task 任务正在调度,也没有任务正在执行<ol><li>调度改任务</li></ol></li></ol></li></ol></li><li>timer 回调执行<ol><li>判断 timerQueue 中任务是否过期,加入 taskQueue</li><li>如果没有 task 任务正在调度<ol><li>是否有 task 任务需要调度?有的话调度,没有才执行第二步</li><li>是否需要设置 timer 回调</li></ol></li></ol></li><li>任务调度执行<ol><li>取消 timer 回调</li><li>检查 timer 中是否有任务需要插入 taskQueue</li><li>执行任务</li><li>判断是否有剩余任务,是否还有剩余时间<ol><li>如果没有剩余时间,有剩余任务,设置新的 task 调度</li></ol></li></ol></li></ol><p><img src="/./Scheduler.assets/4704c25f23fc47158afe7656b5f6e2be.png" alt="img"></p><h3 id="2、主要函数"><a href="#2、主要函数" class="headerlink" title="2、主要函数"></a>2、主要函数</h3><p>scheduleCallback</p><p>shouldYield</p><h2 id="四、其他"><a href="#四、其他" class="headerlink" title="四、其他"></a>四、其他</h2><h3 id="1、线上页面"><a href="#1、线上页面" class="headerlink" title="1、线上页面"></a>1、线上页面</h3><p>vercel地址:<a href="https://scheduler-laborer-dp23rmkfo-brotaone.vercel.app/">打工人的一天 (scheduler-laborer-dp23rmkfo-brotaone.vercel.app)</a></p><p>Codes sandbox: <a href="https://codesandbox.io/p/github/BrotaOne/scheduler-laborer/main?file=/webpack.config.js:1,1&workspaceId=51144849-7844-4340-a304-2a7fdc93390f">scheduler-laborer/main - CodeSandbox</a></p><h3 id="2、不足"><a href="#2、不足" class="headerlink" title="2、不足"></a>2、不足</h3><p>任务无法暂停</p><p>除了 <code>scheduler</code> 维护的队列,应用程序可能也需要维护一个队列,避免同样的任务被反复添加</p><h4 id="3、参考"><a href="#3、参考" class="headerlink" title="3、参考"></a>3、参考</h4><p><a href="https://juejin.cn/post/7171728961473347614">300 行代码实现 React 的调度器 Scheduler - 掘金 (juejin.cn)</a></p><p><a href="https://juejin.cn/post/7046217872833511454">不用一行代码,搞懂React调度器原理 - 掘金 (juejin.cn)</a></p><p><a href="https://mp.weixin.qq.com/s?__biz=MzkzMjIxNTcyMA==&mid=2247489391&idx=1&sn=bf420bb9013f0093cd897b1865b62681&chksm=c25e79a8f529f0bea56db9adfb95f4b933982c96afbb9674eda6693e67d591c5b19ce41f0f37&token=1599882398&lang=zh_CN#rd">100行代码实现React核心调度功能 (qq.com)</a></p><p><img src="/./Scheduler.assets/13528958b6804c16a1dafb613d24b8a9.png" alt="image.png"></p>]]></content>
<summary type="html"><p><strong>基于 React 18.2.0 版本</strong></p>
<h2 id="一、Scheduler-特点"><a href="#一、Scheduler-特点" class="headerlink" title="一、Scheduler 特点"></a>一</summary>
<category term="编程" scheme="https://brotaone.github.io/tags/%E7%BC%96%E7%A8%8B/"/>
<category term="前端" scheme="https://brotaone.github.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>浏览器中的web work</title>
<link href="https://brotaone.github.io/2023/11/23/%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E7%9A%84web%20work/"/>
<id>https://brotaone.github.io/2023/11/23/%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E7%9A%84web%20work/</id>
<published>2023-11-23T07:02:17.000Z</published>
<updated>2025-03-04T09:05:17.911Z</updated>
<content type="html"><![CDATA[<p>参考:</p><ul><li><a href="https://juejin.cn/post/7139718200177983524">一文彻底学会使用web worker</a></li><li><a href="https://juejin.cn/post/6941680632921587719">基于 Service Worker 进行多页面通信 | 项目复盘</a></li></ul><h1 id="Web-Worker"><a href="#Web-Worker" class="headerlink" title="Web Worker"></a>Web Worker</h1><h2 id="Web-Worker-是什么"><a href="#Web-Worker-是什么" class="headerlink" title="Web Worker 是什么"></a>Web Worker 是什么</h2><p>Web Worker 是 HTML5 标准的一部分,这一规范定义了一套 API,允许我们在 js 主线程之外开辟新的 Worker 线程,并将一段 js 脚本运行其中,它赋予了开发者利用 js 操作多线程的能力。<br>因为是独立的线程,Worker 线程与 js 主线程能够同时运行,互不阻塞。所以,在我们有大量运算任务时,可以把运算任务交给 Worker 线程去处理,当 Worker 线程计算完成,再把结果返回给 js 主线程。这样,js 主线程只用专注处理业务逻辑,不用耗费过多时间去处理大量复杂计算,从而减少了阻塞时间,也提高了运行效率,页面流畅度和用户体验自然而然也提高了。</p><h2 id="Web-Worker-能干些什么"><a href="#Web-Worker-能干些什么" class="headerlink" title="Web Worker 能干些什么"></a>Web Worker 能干些什么</h2><p>虽然 Worker 线程是在浏览器环境中被唤起,但是它与当前页面窗口运行在不同的全局上下文中,我们常用的顶层对象 window,以及 parent 对象在 Worker 线程上下文中是不可用的。另外,在 Worker 线程上下文中,操作 DOM 的行为也是不可行的,document对象也不存在。但是,location和navigator对象可以以可读方式访问。除此之外,绝大多数 Window 对象上的方法和属性,都被共享到 Worker 上下文全局对象 WorkerGlobalScope 中。同样,Worker 线程上下文也存在一个顶级对象 self。</p><p>详细信息请参考:<a href="https://link.juejin.cn/?target=https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers">Functions and classes available to Web Workers</a></p><h2 id="Web-Worker-分类"><a href="#Web-Worker-分类" class="headerlink" title="Web Worker 分类"></a>Web Worker 分类</h2><p>除了new Worker外,还有 SharedWorker 和 ServiceWorker</p><h1 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h1><ul><li>Web Worker 疑似不同页面都是共享的一个线程运行的,在一个页面断点暂停后,其他页面也会暂停</li><li>Web Worker 的访问方式和其他文件不同,需要能在根目录访问,而且文件名需要固定,不能被混淆,通常在 webpack 或 vite 中直接放在 public 目录下即可</li><li>由于访问方式的限制,只能引用可以同样方式访问的文件,或者使用 url 路径(不能使用项目中的 npm 包)</li><li>SharedWorker 需要在 edge://inspect/#workers 中才能看到 console.log 的输出,而 ServiceWorker 两个页面都能看到,Woker 只能在当前页面看到</li></ul><h1 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h1><h2 id="Web-Worker-1"><a href="#Web-Worker-1" class="headerlink" title="Web Worker"></a>Web Worker</h2><p>Web Wokrer 相比另外两种比较简单,需要注意传递的是值而不是引用,而且只能传可以是由结构化克隆算法处理的任何值或 JavaScript 对象,包括循环引用</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.js</span></span><br><span class="line"><span class="keyword">const</span> worker = <span class="keyword">new</span> <span class="title class_">Worker</span>(<span class="string">'./worker.js'</span>)</span><br><span class="line">worker.<span class="title function_">postMessage</span>(<span class="string">'hello'</span>)</span><br><span class="line">worker.<span class="property">onmessage</span> = <span class="function">(<span class="params">e</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(e.<span class="property">data</span>)</span><br><span class="line">}</span><br><span class="line">worker.<span class="title function_">addEventListener</span>(<span class="string">'message'</span>, <span class="function"><span class="params">e</span> =></span> { <span class="comment">// 接收消息</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(e.<span class="property">data</span>); <span class="comment">// Greeting from Worker.js,worker线程发送的消息</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// worker.js</span></span><br><span class="line">self.<span class="title function_">postMessage</span>(<span class="string">'Greeting from Worker.js'</span>); <span class="comment">// 发送消息</span></span><br><span class="line">self.<span class="title function_">addEventListener</span>(<span class="string">'message'</span>, <span class="function"><span class="params">e</span> =></span> { <span class="comment">// 接收消息</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(e.<span class="property">data</span>); <span class="comment">// hello,主线程发送的消息</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="SharedWorker"><a href="#SharedWorker" class="headerlink" title="SharedWorker"></a>SharedWorker</h2><p>如果采用 onmessage 方法,则默认开启端口,不需要再手动调用SharedWorker.port.start()方法</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.js</span></span><br><span class="line"><span class="keyword">const</span> worker = <span class="keyword">new</span> <span class="title class_">SharedWorker</span>(<span class="string">'./sharedWorker.js'</span>)</span><br><span class="line">worker.<span class="property">port</span>.<span class="title function_">start</span>(); <span class="comment">// 开启端口</span></span><br><span class="line">worker.<span class="property">port</span>.<span class="title function_">postMessage</span>(<span class="string">'hello'</span>)</span><br><span class="line">worker.<span class="property">port</span>.<span class="title function_">addEventListener</span>(<span class="string">'message'</span>, <span class="function"><span class="params">e</span> =></span> { <span class="comment">// 接收消息</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(e.<span class="property">data</span>); <span class="comment">// Greeting from Worker.js,worker线程发送的消息</span></span><br><span class="line">});</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// sharedWorker.js</span></span><br><span class="line"><span class="keyword">let</span> num = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">const</span> workerList = [];</span><br><span class="line"></span><br><span class="line">self.<span class="title function_">addEventListener</span>(<span class="string">'connect'</span>, <span class="function"><span class="params">e</span> =></span> {</span><br><span class="line"> <span class="keyword">const</span> port = e.<span class="property">ports</span>[<span class="number">0</span>];</span><br><span class="line"> port.<span class="title function_">addEventListener</span>(<span class="string">'message'</span>, <span class="function"><span class="params">e</span> =></span> {</span><br><span class="line"> num += e.<span class="property">data</span> === <span class="string">'add'</span> ? <span class="number">1</span> : -<span class="number">1</span>;</span><br><span class="line"> workerList.<span class="title function_">forEach</span>(<span class="function"><span class="params">port</span> =></span> { <span class="comment">// 遍历所有已连接的part,发送消息</span></span><br><span class="line"> port.<span class="title function_">postMessage</span>(num);</span><br><span class="line"> })</span><br><span class="line"> });</span><br><span class="line"> port.<span class="title function_">start</span>();</span><br><span class="line"> workerList.<span class="title function_">push</span>(port); <span class="comment">// 存储已连接的part</span></span><br><span class="line"> port.<span class="title function_">postMessage</span>(num); <span class="comment">// 初始化</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>但是如果要用这种方式来处理,多页面共享的话,似乎不是很方便,甚至不如用 ServiceWorker</p><h2 id="ServiceWorker"><a href="#ServiceWorker" class="headerlink" title="ServiceWorker"></a>ServiceWorker</h2><p>之前我以为 ServiceWorker 不能从 Worker postMessage给主线程,需要借助其他方式,比如在 connect 时用 MessageChannel 传递 port,但是实际上可以用 self。clients,已经维护好了所有的 页面</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.js</span></span><br><span class="line"><span class="keyword">if</span> (<span class="string">'serviceWorker'</span> <span class="keyword">in</span> navigator) {</span><br><span class="line"> navigator.<span class="property">serviceWorker</span>.<span class="title function_">register</span>(<span class="string">'./serviceWorker.js'</span>).<span class="title function_">then</span>(<span class="function"><span class="params">registration</span> =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'service worker 注册成功'</span>)</span><br><span class="line"> }).<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'servcie worker 注册失败'</span>)</span><br><span class="line"> })</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">useNotification</span> = (<span class="params"></span>) => {</span><br><span class="line"> <span class="keyword">const</span> [data, setData] = <span class="title function_">useState</span>({});</span><br><span class="line"> <span class="title function_">useEffect</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="string">"serviceWorker"</span> <span class="keyword">in</span> navigator) {</span><br><span class="line"> <span class="keyword">let</span> <span class="title function_">listener</span> = (<span class="params">event</span>) => {</span><br><span class="line"> <span class="keyword">const</span> clientId = event.<span class="property">data</span>.<span class="property">client</span>;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`receive message from <span class="subst">${clientId}</span>`</span>);</span><br><span class="line"> <span class="title function_">setData</span>(event.<span class="property">data</span>);</span><br><span class="line"> };</span><br><span class="line"> navigator.<span class="property">serviceWorker</span>.<span class="title function_">addEventListener</span>(<span class="string">"message"</span>, listener);</span><br><span class="line"> <span class="keyword">return</span> <span class="function">() =></span> {</span><br><span class="line"> navigator.<span class="property">serviceWorker</span>.<span class="title function_">removeEventListener</span>(<span class="string">"message"</span>, listener);</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line"> }, []);</span><br><span class="line"> <span class="keyword">const</span> postMessage = <span class="title function_">useCallback</span>(<span class="function">(<span class="params">message</span>) =></span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="string">"serviceWorker"</span> <span class="keyword">in</span> navigator) {</span><br><span class="line"> navigator.<span class="property">serviceWorker</span>.<span class="property">controller</span>.<span class="title function_">postMessage</span>(message);</span><br><span class="line"> }</span><br><span class="line"> }, []);</span><br><span class="line"> <span class="keyword">return</span> [data, postMessage];</span><br><span class="line">};</span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// serviceWorker.js</span></span><br><span class="line"><span class="comment">/* eslint-disable no-restricted-globals */</span></span><br><span class="line"><span class="keyword">import</span> { clientsClaim } <span class="keyword">from</span> <span class="string">"workbox-core"</span>;</span><br><span class="line"><span class="keyword">import</span> { precacheAndRoute } <span class="keyword">from</span> <span class="string">"workbox-precaching"</span>;</span><br><span class="line"></span><br><span class="line"><span class="title function_">clientsClaim</span>();</span><br><span class="line"><span class="title function_">precacheAndRoute</span>(self.<span class="property">__WB_MANIFEST</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 监听来自网页客户端的消息</span></span><br><span class="line">self.<span class="title function_">addEventListener</span>(<span class="string">"message"</span>, <span class="function">(<span class="params">event</span>) =></span> {</span><br><span class="line"> <span class="keyword">if</span> (event.<span class="property">data</span> && event.<span class="property">data</span>.<span class="property">type</span> === <span class="string">"SKIP_WAITING"</span>) {</span><br><span class="line"> self.<span class="title function_">skipWaiting</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> promise = self.<span class="property">clients</span>.<span class="title function_">matchAll</span>().<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params">clientList</span>) {</span><br><span class="line"> <span class="keyword">var</span> senderID = event.<span class="property">source</span>.<span class="property">id</span>;</span><br><span class="line"> <span class="comment">// 消息不传递给发送者本身</span></span><br><span class="line"> clientList.<span class="title function_">forEach</span>(<span class="keyword">function</span> (<span class="params">client</span>) {</span><br><span class="line"> <span class="keyword">if</span> (client.<span class="property">id</span> === senderID) {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> client.<span class="title function_">postMessage</span>({</span><br><span class="line"> <span class="attr">client</span>: senderID,</span><br><span class="line"> <span class="attr">message</span>: event.<span class="property">data</span>,</span><br><span class="line"> });</span><br><span class="line"> });</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">if</span> (event.<span class="property">waitUntil</span>) {</span><br><span class="line"> event.<span class="title function_">waitUntil</span>(promise);</span><br><span class="line"> }</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>ServiceWorker 可以拦截请求,可以做缓存和 PWA(Progressive Web App)</p>]]></content>
<summary type="html"><p>参考:</p>
<ul>
<li><a href="https://juejin.cn/post/7139718200177983524">一文彻底学会使用web worker</a></li>
<li><a href="https://juejin.cn/post/694</summary>
<category term="编程" scheme="https://brotaone.github.io/tags/%E7%BC%96%E7%A8%8B/"/>
<category term="前端" scheme="https://brotaone.github.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>我和我的聪明</title>
<link href="https://brotaone.github.io/2021/09/12/myCatCute/"/>
<id>https://brotaone.github.io/2021/09/12/myCatCute/</id>
<published>2021-09-12T07:43:10.000Z</published>
<updated>2025-03-04T09:05:17.299Z</updated>
<content type="html">< --><!--  --><!--  --><p><img src="/2021/09/12/myCatCute/IMG_0190.jpeg" alt="闲鱼上的聪明"></p><p><img src="/2021/09/12/myCatCute/IMG_0191.jpeg" alt="闲鱼上的聪明"></p><p><img src="/2021/09/12/myCatCute/IMG_0192.jpeg" alt="闲鱼上的聪明"></p><p><img src="/2021/09/12/myCatCute/IMG_0193.jpeg" alt="闲鱼上的聪明"></p><h1 id="冲突逐渐增多"><a href="#冲突逐渐增多" class="headerlink" title="冲突逐渐增多"></a>冲突逐渐增多</h1><h1 id="现在的聪明"><a href="#现在的聪明" class="headerlink" title="现在的聪明"></a>现在的聪明</h1>]]></content>
<summary type="html"><p>聪明是一只猫,蓝白猫,脸上的胡须特别多,第一眼看上去不是很好看的那种</p>
<h1 id="闲鱼买猫"><a href="#闲鱼买猫" class="headerlink" title="闲鱼买猫"></a>闲鱼买猫</h1><p>几年前,我就萌生过养猫的想法。记得小时候</summary>
</entry>
<entry>
<title>前端学习的摸索</title>
<link href="https://brotaone.github.io/2021/09/12/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E7%9A%84%E6%91%B8%E7%B4%A2/"/>
<id>https://brotaone.github.io/2021/09/12/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E7%9A%84%E6%91%B8%E7%B4%A2/</id>
<published>2021-09-12T07:02:17.000Z</published>
<updated>2025-03-04T09:05:17.910Z</updated>
<content type="html"><![CDATA[<p>从一年前开始学习前端,现在才不多已经要一年了。转眼间现在就已经是研三了,经历过2019年的秋招,现在春招都开始了这么长时间,我却依旧没有offer,真的让人难受啊,想着现在还有毕业论文的事请没有做,感觉时间很紧迫,有点慌,又怕找不到工作,又怕耽误毕业,哎!希望昨天面试的能够拿到offer吧!</p><p> 希望能找到北京的工作,虽然以后的空闲时间会很少,但是我也不介意,大不了以后就一周玩一会主机游戏就好。</p><p> 好了,言归正传,回顾一下我之前的前端学习,和以后应该如何学习吧!</p><p>初始学习<br> 刚开始学习,我是看着最基础的HTML、CSS、JAVASCRIPT学的,因为懒,就先直接看了菜鸟教程的教学跟着学习,当时就感觉好简单啊,都只是一些随便记一下就可以用的语法规则,感觉都不需要学习多久。</p><p> 然而事实证明,我只看到了最肤浅的东西,看了HTML、CSS基础的教学,却连基本布局都不知道,不知道怎么用float、清楚浮动、高度塌陷,别说flex布局、grid布局,连圣杯和双飞燕布局都写不好。JAVASCRIPT也只是会最简单的语法,不会ES6,也不知道深层次的问题。</p><p> 就是这样的状态,我开始了秋招(现在想想我要是随便加了个前端学习的群,然后问人,应该怎么学就好了啊,可惜现在似乎有点晚了),面试的第一家,前面都很顺利,问了算法为主,最后问setTimeout和promise执行顺序的时候,我之前看过,但是没有弄懂到底怎么回事,于是就崩了,哎!</p><p> 之后的面试,也是暴露了对很多基础东西的把握不够,计算机网络了解得少,不知道tcp/udp连接、http和https协议,也不知道缓存使用,之前得算法学习也一直看到难的就不想做,觉得差不多了,就去玩主机游戏了,感觉荒废了很多时间。而且我对前端框架的了解也非常少,甚至还想通过微信小程序的前端框架,来学习,其实前端框架也很简单的,如果不看源码,也就是使用api和JavaScript编程。</p><p>最近的学习<br> 经历了秋招的失败,我一方面想学习框架,一方面我想学习前端框架vue,一方面想通过ES6巩固JavaScript。</p><p> 然而寒假刚开始,我想的是在家好好玩几天(终于有时间再玩黑暗之魂1 重制版了),然后2月6号回学校,还有半个月的时间好好复习,然而没想到新冠肺炎让我3月17号都还呆在家里,不得不在家复习了。</p><p>今后打算<br> ES6的内容比我想的多很多,还要继续学习,如果可以的话,想看jQuery源码、Vue源码,对于尤雨溪大佬,一个人开始Vue开发,到现在一个小团队开发,成为前端三大框架之一,我只有佩服的份,希望能一天天减小与大佬的差距。</p><p> CSS,我还是需要好好巩固一下布局,学习各种动画,SVG、CANVAS也是要学习的。</p><p> 前端框架先好好学习API,然后看看实现方法,源码就以后再说吧。</p><p> 目前在看的教材有阮一峰大佬的ES6,你不知道的JavaScript,还有CSS揭秘,然后每天刷刷算法题,看看别人的面经查漏补缺,再抽空准备毕业的事吧。</p><p> 今年大家过的都不容易啊,虽然我在家啥都没表现出来,其实内心慌的一批,好担心找不到工作,然后还得住在住女朋友那,想想就可怕,回家过是不可能的,毕竟好不容易从南昌跑到北京,怎么可能再回去呢?</p>]]></content>
<summary type="html"><p>从一年前开始学习前端,现在才不多已经要一年了。转眼间现在就已经是研三了,经历过2019年的秋招,现在春招都开始了这么长时间,我却依旧没有offer,真的让人难受啊,想着现在还有毕业论文的事请没有做,感觉时间很紧迫,有点慌,又怕找不到工作,又怕耽误毕业,哎!希望昨天面试的能够</summary>
<category term="编程" scheme="https://brotaone.github.io/tags/%E7%BC%96%E7%A8%8B/"/>
<category term="前端" scheme="https://brotaone.github.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>魂类游戏</title>
<link href="https://brotaone.github.io/2021/09/12/%E9%AD%82%E7%B1%BB%E6%B8%B8%E6%88%8F/"/>
<id>https://brotaone.github.io/2021/09/12/%E9%AD%82%E7%B1%BB%E6%B8%B8%E6%88%8F/</id>
<published>2021-09-12T06:58:53.000Z</published>
<updated>2025-03-04T09:05:17.911Z</updated>
<content type="html"><![CDATA[<h1 id="最早的接触:血源"><a href="#最早的接触:血源" class="headerlink" title="最早的接触:血源"></a>最早的接触:血源</h1><p>在研一上学期买了PS4 slim之后,就听说了“新人”必玩的三大游戏:黑魂、血源、仁王,黑魂、血源都是游戏公司From Software制作的,入门难度都非常高,售价也都不低,在研一上的考试周,我在淘宝买了二手的血源PS4光盘,想开始我的受苦之旅。</p><p>然而让我没想到的是,这一买,就是一年都没有通关。别说第一个boss教父了,连一个精英怪神职人员野兽都打不过,打了十多个小时,还在第一个区域逛,于是只好作罢,暂时玩一起买的恶灵附身了。</p><h1 id="Steam上再战魂系列:黑魂3"><a href="#Steam上再战魂系列:黑魂3" class="headerlink" title="Steam上再战魂系列:黑魂3"></a>Steam上再战魂系列:黑魂3</h1><p>再玩魂系列游戏,就是买了游戏本机械革命z2之后了,由于囊中羞涩,只买了低配版i5-8300h配gtx1060,现在是2020年2月17日,感觉玩游戏也还可以,我也在2019年3月左右闲鱼出了PS4 slim,同年6月考拉入手了PS4 pro,新游戏用PS4玩也没有什么问题。</p><p>买了机械革命之后,在十月的万圣节促销中看到了黑魂3的折扣,于是就抑制不了冲动再次开始了受苦之旅。</p><p>然而这次虽然一样受苦但是比上回好多了,在新人导师古达那学习了近2个小时之后,终于侥幸过关,来到了传火祭祀场,然而刚到祭祀场却连路都不知道在哪,还被又一新人杀手太刀哥虐了千百回。后面又在高墙受苦好几回,虽然由于宿舍网不好,我通常都是单机玩,于是侥幸躲过了高墙薪王的洗礼,但是面对洛斯里克骑士和冰狗波尔多仍旧是受苦练练。</p><p>后来好不容易打到了不死聚落,第一回想捏余火加血,却被npc入侵,加上小怪的夹击,有一次殒命。好不容易打到了不死聚落的高塔,却由于太过害怕,把摩恩当作小怪砍了一刀,于是又迎来和摩恩的战斗。</p><p>由于打不过大树,我又一次暂停了魂系列游玩,再玩就是寒假放假回家玩了。然后回到学校之后也继续玩了段时间,陆续打了法兰不死队、老恶魔王、结晶老者、教堂boss(忘记名字了)、剑宗沙立万、吞噬申明的艾尔德里奇、巨人王尤姆、舞娘,之后的大盾boss(忘了名字了)、双王子、薪王化身都是线上找好太阳过的,算是逃课了,dlc进去玩了会也被劝退了,难度提高了不少。</p><h1 id="PS4-PRO-再战血源"><a href="#PS4-PRO-再战血源" class="headerlink" title="PS4 PRO 再战血源"></a>PS4 PRO 再战血源</h1><p>由于通关黑魂3(本体)给我带来的信心,于是我再一次拾起了血源。</p><p>与上次不同,这次虽然依旧受苦,但是我已经能打过很多boss了,甚至打到了dlc,除了科斯孤儿和劳伦斯打不过外,还有本体的boss不想先打,其他boss都打过了,尤其是没用枪反打过了女boss(再一次忘记了名字)。</p><h1 id="只狼"><a href="#只狼" class="headerlink" title="只狼"></a>只狼</h1><p>和之前的魂系列游戏不同,只狼取消了经历条,取而代之是招架条,虽然可以让玩家更莽了,我却是更加受苦了,再多次挑战二次猿失败后开启了开怪逃课之路。</p><h1 id="STEAM-魂2-SWITCH-魂1"><a href="#STEAM-魂2-SWITCH-魂1" class="headerlink" title="STEAM 魂2, SWITCH 魂1"></a>STEAM 魂2, SWITCH 魂1</h1><p>血源打过之后,信心爆棚,又买了黑魂2,虽然看到网上说魂2更加受苦,堆怪、加上地图更加恶意。然而我还是小瞧了魂2,想着有经验了,应该不怕,听说法师很牛逼之后,甚至第一个上手吧法师职业,结果发现法师法术次数不够用、施术太慢,依旧受苦,后面也就弃了。</p><p>后来发现ns上有黑暗之魂1 重制版,可以掌上受苦,而且听说魂1的法师很强,于是按捺不住自己想玩无双黑魂的心,又买了魂1。好在魂1我是通关了好几回,加上有弹反捏魂,打不过就刷魂呗,反正是arpg游戏,现在有个存档都玩到了3周目了。</p><h1 id="之后的期待"><a href="#之后的期待" class="headerlink" title="之后的期待"></a>之后的期待</h1><p>19年6月的游戏展上,Form Software公司宣布了新游戏 Eleden Ring,期待早日开售。<br>没想到19年12月的新冠肺炎影响到了2020年的游戏展、奥运会、NBA,全球几十亿人,哎,好在游戏还是可以在网上看发布会。</p><h1 id="PS4-PRO-再战魂二"><a href="#PS4-PRO-再战魂二" class="headerlink" title="PS4 PRO 再战魂二"></a>PS4 PRO 再战魂二</h1><h1 id="仁王"><a href="#仁王" class="headerlink" title="仁王"></a>仁王</h1><h1 id="XSX-三战魂二"><a href="#XSX-三战魂二" class="headerlink" title="XSX 三战魂二"></a>XSX 三战魂二</h1><h1 id="XSX-二战只狼"><a href="#XSX-二战只狼" class="headerlink" title="XSX 二战只狼"></a>XSX 二战只狼</h1>]]></content>
<summary type="html"><h1 id="最早的接触:血源"><a href="#最早的接触:血源" class="headerlink" title="最早的接触:血源"></a>最早的接触:血源</h1><p>在研一上学期买了PS4 slim之后,就听说了“新人”必玩的三大游戏:黑魂、血源、仁王,黑魂</summary>
<category term="game" scheme="https://brotaone.github.io/categories/game/"/>
<category term="game" scheme="https://brotaone.github.io/tags/game/"/>
<category term="soul-like" scheme="https://brotaone.github.io/tags/soul-like/"/>
</entry>
</feed>