<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>JavaScript - 标签 - lihuu — 系统工程、AI 工具链与 Rust 开发博客</title>
        <link>https://silentstormic.top/tags/JavaScript/</link>
        <description>JavaScript - 标签 - lihuu — 系统工程、AI 工具链与 Rust 开发博客</description>
        <generator>Hugo -- gohugo.io</generator><language>zh-CN</language><lastBuildDate>Thu, 08 May 2025 10:23:49 &#43;0800</lastBuildDate><atom:link href="https://silentstormic.top/tags/JavaScript/" rel="self" type="application/rss+xml" /><item>
    <title>Server-Sent Events: 实现高效的实时Web通信</title>
    <link>https://silentstormic.top/post/sse/</link>
    <pubDate>Thu, 08 May 2025 10:23:49 &#43;0800</pubDate>
    <author>lihuu</author>
    <guid>https://silentstormic.top/post/sse/</guid>
    <description><![CDATA[<h2 id="server-sent-events-概述">Server-Sent Events 概述</h2>
<p>Server-Sent Events（SSE）是一种基于 HTTP 协议的服务器推送技术，它允许服务器以流的方式向客户端实时推送数据。与 WebSocket 等双向通信技术不同，SSE 专注于单向通信（从服务器到客户端），特别适合需要服务器主动推送数据的场景，如：</p>
<ul>
<li>社交媒体的实时通知（评论、点赞、关注提醒）</li>
<li>股票价格、体育比分的实时更新</li>
<li>日志和事件流的实时监控</li>
<li>聊天应用中的消息提醒</li>
</ul>
<h3 id="sse-与-websocket-的对比">SSE 与 WebSocket 的对比</h3>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>Server-Sent Events</th>
          <th>WebSocket</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>通信方向</td>
          <td>单向（服务器到客户端）</td>
          <td>双向</td>
      </tr>
      <tr>
          <td>协议</td>
          <td>标准 HTTP</td>
          <td>WebSocket 协议（基于 HTTP 握手）</td>
      </tr>
      <tr>
          <td>实现复杂度</td>
          <td>低，使用现有的 HTTP 基础设施</td>
          <td>相对较高，需要特殊的服务器支持</td>
      </tr>
      <tr>
          <td>重连机制</td>
          <td>内置自动重连</td>
          <td>需要手动实现</td>
      </tr>
      <tr>
          <td>浏览器支持</td>
          <td>所有现代浏览器（IE 需要 polyfill）</td>
          <td>所有现代浏览器</td>
      </tr>
      <tr>
          <td>数据格式</td>
          <td>文本（通常是 JSON）</td>
          <td>文本或二进制</td>
      </tr>
      <tr>
          <td>适用场景</td>
          <td>服务器频繁更新客户端</td>
          <td>需要频繁双向数据交换</td>
      </tr>
  </tbody>
</table>
<h3 id="sse-工作原理">SSE 工作原理</h3>
<p>SSE 的实现原理非常简单。客户端通过 JavaScript 的 <code>EventSource</code> 接口发起请求，服务器保持连接打开并定期发送事件。这种连接具有以下特点：</p>]]></description>
</item>
<item>
    <title>Perttier 使用</title>
    <link>https://silentstormic.top/post/perttier/</link>
    <pubDate>Sat, 13 Apr 2024 21:02:05 &#43;0800</pubDate>
    <author>lihuu</author>
    <guid>https://silentstormic.top/post/perttier/</guid>
    <description><![CDATA[<h2 id="perttier-使用">Perttier 使用</h2>
<h3 id="官网">官网</h3>
<p><a href="https://prettier.io/docs/en/index.html" target="_blank" rel="noopener noreffer ">What is Prettier? · Prettier</a></p>
<h3 id="安装">安装</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right fa-fw" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h fa-fw" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy fa-fw" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 全局安装</span>
</span></span><span class="line"><span class="cl">npm install -g prettier
</span></span><span class="line"><span class="cl"><span class="c1"># or</span>
</span></span><span class="line"><span class="cl">yarn global add pretter
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 项目中安装</span>
</span></span><span class="line"><span class="cl">npm install --save-dev --save-exact prettier
</span></span><span class="line"><span class="cl"><span class="c1">#or</span>
</span></span><span class="line"><span class="cl">yarn add prettier --dev --exact</span></span></code></pre></div></div>
<h3 id="配置">配置</h3>
<h4 id="配置的位置">配置的位置</h4>
<ul>
<li>
<p><code>package.json</code> 中的 <code>perttier</code> 字段</p>
</li>
<li>
<p>JSON 或者 YAML 格式的 <code>.prettierrc</code></p>
</li>
<li>
<p><code>.prettierrc.json</code>, <code>.prettierrc.yml</code> , <code>.prettierrc.yaml</code>, <code>.prettierrc.json5</code></p>
</li>
<li>
<p><code>.prettierrc.js</code> , <code>.prettierrc.cjs</code> ,<code>prettierrc.config.js</code>,<code>prettierrc.config.cjs</code></p>
</li>
</ul>
<div class="code-block code-line-numbers" style="counter-reset: code-block 0">
    <div class="code-header language-json">
        <span class="code-title"><i class="arrow fas fa-angle-right fa-fw" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h fa-fw" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy fa-fw" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;tabWidth&#34;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="c1">// tab缩进大小,默认为2
</span></span></span><span class="line"><span class="cl">  <span class="nt">&#34;useTabs&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> <span class="c1">// 使用tab缩进，默认false
</span></span></span><span class="line"><span class="cl">  <span class="nt">&#34;semi&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="c1">// 使用分号, 默认true
</span></span></span><span class="line"><span class="cl">  <span class="nt">&#34;singleQuote&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> <span class="c1">// 使用单引号, 默认false(在jsx中配置无效, 默认都是双引号)
</span></span></span><span class="line"><span class="cl">  <span class="nt">&#34;TrailingCooma&#34;</span><span class="p">:</span> <span class="s2">&#34;none&#34;</span><span class="p">,</span> <span class="c1">// 行尾逗号,默认none,可选 none|es5|all,es5 包括es5中的数组、对象,all 包括函数对象等所有可选
</span></span></span><span class="line"><span class="cl">  <span class="nt">&#34;bracketSpacing&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> <span class="c1">// 对象中的空格 默认true
</span></span></span><span class="line"><span class="cl">  <span class="nt">&#34;jsxBracketSameLine&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="c1">// JSX标签闭合位置 默认false
</span></span></span><span class="line"><span class="cl">  <span class="nt">&#34;arrowParens&#34;</span><span class="p">:</span> <span class="s2">&#34;avoid&#34;</span><span class="p">,</span> <span class="c1">// 箭头函数参数括号，默认avoid 可选 avoid| always,avoid 能省略括号的时候就省略 例如x =&gt; x，always 总是有括号
</span></span></span><span class="line"><span class="cl">  <span class="nt">&#34;htmlWhitespaceSensitivity&#34;</span><span class="p">:</span> <span class="s2">&#34;strict&#34;</span> <span class="c1">//html空格严格程度，可选&lt;css|strict|ignore&gt;
</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p>配置文件的位置从被格式化的文件的位置找起，然后沿着文件系统向上寻找。注意，prettier 没有全局的配置文件。</p>]]></description>
</item>
<item>
    <title>Javascript 宏任务和微任务</title>
    <link>https://silentstormic.top/post/javascript-task/</link>
    <pubDate>Thu, 21 Jan 2021 17:10:45 &#43;0800</pubDate>
    <author>lihuu</author>
    <guid>https://silentstormic.top/post/javascript-task/</guid>
    <description><![CDATA[<h4 id="宏任务">宏任务</h4>
<p>由宿主发起的任务称为宏观任务。<br/>
例如<code>setTimeout</code>函数创建的就是宏任务，当前的脚本执行也是宏任务。</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-javascript">
        <span class="code-title"><i class="arrow fas fa-angle-right fa-fw" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h fa-fw" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy fa-fw" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">setTimeout</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;Hello&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span> <span class="mi">100</span><span class="p">);</span></span></span></code></pre></div></div>
<h4 id="微任务">微任务</h4>
<p>由 JavaScript 引擎发起的任务称为微任务。<br/>
微任务的主要来源是<code>Promise</code>。
在 JavaScript 的事件循环中，当期宏任务执行完或者如果调用栈为空的时候，会检查微任务队列，如果队列不为空，会执行微任务队列中的任务。</p>]]></description>
</item>
<item>
    <title>Electron实例代码</title>
    <link>https://silentstormic.top/post/Electron%E5%AE%9E%E4%BE%8B%E4%BB%A3%E7%A0%81/</link>
    <pubDate>Mon, 11 Nov 2019 16:00:07 &#43;0800</pubDate>
    <author>lihuu</author>
    <guid>https://silentstormic.top/post/Electron%E5%AE%9E%E4%BE%8B%E4%BB%A3%E7%A0%81/</guid>
    <description><![CDATA[<h3 id="electron-实例代码">Electron 实例代码</h3>
<p>以下是一些比较实用的<code>Electron</code>的代码。</p>
<h4 id="为应用程序添加右键菜单">为应用程序添加右键菜单</h4>
<p>这段代码应该添加到 html 中的页面中</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-javascript">
        <span class="code-title"><i class="arrow fas fa-angle-right fa-fw" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h fa-fw" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy fa-fw" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="o">&lt;</span><span class="nx">script</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">remote</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;electron&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">Menu</span><span class="p">,</span> <span class="nx">MenuItem</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">remote</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">menu</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Menu</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nx">menu</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="k">new</span> <span class="nx">MenuItem</span><span class="p">({</span> <span class="nx">label</span><span class="o">:</span> <span class="s1">&#39;MenuItem1&#39;</span><span class="p">,</span> <span class="nx">click</span><span class="p">()</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;item 1 clicked&#39;</span><span class="p">)</span> <span class="p">}</span> <span class="p">}));</span>
</span></span><span class="line"><span class="cl"><span class="nx">menu</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="k">new</span> <span class="nx">MenuItem</span><span class="p">({</span> <span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;separator&#39;</span> <span class="p">}));</span>
</span></span><span class="line"><span class="cl"><span class="nx">menu</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="k">new</span> <span class="nx">MenuItem</span><span class="p">({</span> <span class="nx">label</span><span class="o">:</span> <span class="s1">&#39;MenuItem2&#39;</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;checkbox&#39;</span><span class="p">,</span> <span class="nx">checked</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;contextmenu&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="nx">menu</span><span class="p">.</span><span class="nx">popup</span><span class="p">({</span> <span class="nb">window</span><span class="o">:</span> <span class="nx">remote</span><span class="p">.</span><span class="nx">getCurrentWindow</span><span class="p">()</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span> <span class="kc">false</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="err">/script&gt;</span></span></span></code></pre></div></div>
<h4 id="限制只能运行一个实例的代码">限制只能运行一个实例的代码</h4>
<p>限制只能运行一个实例，需要用到 Electron 的 <code>app.requestSingleInstanceLock()</code>方法,
此方法的返回值表示我们的应用程序实例是否成功取得了锁。 如果它取得锁失败，则可以认为已经有一个实例获取了锁，并且正在运行，我们可以使用 <code>app.quit()</code> 方法立即结束当前实例的运行。
调用 <code>app.requestSingleInstanceLock()</code>方法，会触发前一个实例(如果存在前一个实例)的<code>second-instance</code>事件，我们可以在这个事件里面做点什么，例如激活前一个实例的窗口并获取焦点，示例代码如下</p>]]></description>
</item>
<item>
    <title>Eslint 使用</title>
    <link>https://silentstormic.top/post/eslint/</link>
    <pubDate>Thu, 29 Aug 2019 22:11:39 &#43;0800</pubDate>
    <author>lihuu</author>
    <guid>https://silentstormic.top/post/eslint/</guid>
    <description><![CDATA[<h1 id="eslint">ESLint</h1>
<p>ESLint 是一种静态代码分析工具，用于识别 JavaScript 代码中存在的有问题的模式,可以帮助我们写出语法正确，风格统一的代码。</p>
<h2 id="安装以及使用-eslint">安装以及使用 ESLint</h2>
<ol>
<li>我们可以使用 npm 来安装 ESLint，运行<code>npm install eslint --save-dev</code>命令安装 ESlint。</li>
<li>在项目根目录运行<code>./node_modules/.bin/eslint --init</code>命令进行初始化操作，初始化的时候根据命令的提示输入一些基本的设置，确认后会在项目的根目录下面生成一个名字为<code>.eslintrc.*</code>(这个在初始化的时候可以选择不同的文件格式,json 或者 yaml 都是可以的)的配置文件。如下图所示<br/>
</li>
<li>安装配置完成之后就可以直接使用了，可以在任何的文件目录或者文件上运行 <code>./node_modules/.bin/eslint  yourfile.js</code></li>
</ol>
<blockquote>
<p>上述的使用只是在本地安装了 eslint，当然我们完全可以把这货安装成全局的，使用<code>npm install -g eslint</code>，但是呢，全局安装的 eslit 在执行的时候，使用的插件和配置文件还是优先读取本地的,如果在<code>~/</code>目录中存在配置文件，只有在 eslint 没有读取到任何的配置文件的时候才会去读取这里的文件。</p>]]></description>
</item>
</channel>
</rss>
