summaryrefslogtreecommitdiff
path: root/2023/04
diff options
context:
space:
mode:
Diffstat (limited to '2023/04')
-rw-r--r--2023/04/25/二零二三年四月二十五日/index.html2
-rw-r--r--2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/index.html305
2 files changed, 306 insertions, 1 deletions
diff --git a/2023/04/25/二零二三年四月二十五日/index.html b/2023/04/25/二零二三年四月二十五日/index.html
index 52445a8c..ee979d3c 100644
--- a/2023/04/25/二零二三年四月二十五日/index.html
+++ b/2023/04/25/二零二三年四月二十五日/index.html
@@ -180,7 +180,7 @@
<div class="icon arrow-left"></div>
<div class="post-link">
- <a href="/2023/06/10/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AD%E6%9C%88%E5%8D%81%E6%97%A5/">Prev</a>
+ <a href="/2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/">Prev</a>
</div>
</div>
diff --git a/2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/index.html b/2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/index.html
new file mode 100644
index 00000000..1552bd37
--- /dev/null
+++ b/2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/index.html
@@ -0,0 +1,305 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+<title>TypeScript With Rust Errors, No Try Catch, Heresy | 暮秋小屋</title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+<style>
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
+</style>
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script src="/js/frame.js"></script>
+
+
+
+
+
+ <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+
+
+
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="mask-border">
+ </div>
+
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ Menu
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">主页</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">日记本</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">医学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">计算机科学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">生活</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">关于</a>
+ </li>
+
+
+
+ <li class="menu-item search-btn">
+ <a href="#">Search</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <article id="post">
+
+
+ <div class="post-head">
+ <div class="post-info">
+ <div class="tag-list">
+
+
+ <span class="post-tag">
+ <a href="/tags/Technique/">
+ Technique
+ </a>
+ </span>
+
+ <span class="post-tag">
+ <a href="/tags/TypeScript/">
+ TypeScript
+ </a>
+ </span>
+
+
+ </div>
+ <div class="post-title">
+
+
+ TypeScript With Rust Errors, No Try Catch, Heresy
+
+
+ </div>
+ <span class="post-date">
+ Apr 30, 2023
+ </span>
+ </div>
+ <div class="post-img">
+
+ <div class="h-line-primary"></div>
+
+ </div>
+</div>
+ <div class="post-content">
+ <blockquote>
+<p>It’s hard to miss things when you don’t know different things exist</p>
+</blockquote>
+<p>The first problem is, and personally, I believe it’s the biggest JavaScript problem ever: we don’t know what can throw an error. From a JavaScript error perspective, it’s the same as the following:</p>
+<figure class="highlight javascript"><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">try</span> &#123;</span><br><span class="line"> <span class="keyword">let</span> data = “<span class="title class_">Hello</span>”;</span><br><span class="line">&#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(err);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
+
+<p>JavaScript doesn’t know; JavaScript doesn’t care. You should know.</p>
+<p>Second thing, this is perfectly viable code:</p>
+<figure class="highlight javascript"><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="keyword">const</span> request = &#123; <span class="attr">name</span>: “test”, <span class="attr">value</span>: <span class="number">2n</span> &#125;;</span><br><span class="line"><span class="keyword">const</span> body = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(request);</span><br><span class="line"><span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">&quot;https://example.com&quot;</span>, &#123;</span><br><span class="line"> <span class="attr">method</span>: “<span class="variable constant_">POST</span>”,</span><br><span class="line"> body,</span><br><span class="line">&#125;);</span><br><span class="line"><span class="keyword">if</span> (!response.<span class="property">ok</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
+
+<p>No errors, no linters, even though this can break your app.</p>
+<p>Right now, in my head, I can hear, “What’s the problem, just use try&#x2F;catch everywhere.” Here comes the third problem: we don’t know which one is thrown. Of course, we can somehow guess by the error message, but what about bigger services&#x2F;functions with many places where errors can happen? Are you sure you are handling all of them properly with one try&#x2F;catch?</p>
+<hr>
+<figure class="highlight rust"><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">let</span> <span class="variable">greeting_file_result</span> = File::<span class="title function_ invoke__">open</span>(“hello.txt”); </span><br><span class="line"><span class="keyword">let</span> <span class="variable">greeting_file</span> = <span class="keyword">match</span> greeting_file_result &#123; </span><br><span class="line"> <span class="title function_ invoke__">Ok</span>(file) =&gt; file, </span><br><span class="line"> <span class="title function_ invoke__">Err</span>(error) =&gt; <span class="built_in">panic!</span>(<span class="string">&quot;Problem opening the file: &#123;:?&#125;&quot;</span>, error), </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
+
+<p>The most verbose of the three shown here and, ironically, the best one. So, first of all, Rust handles the errors using its amazing enums (they are not the same as TypeScript enums!). Without going into detail, what is important here is that it uses an enum called <code>Result</code> with two variants: <code>Ok</code> and <code>Err</code>. As you might guess, <code>Ok</code> holds a value and <code>Err</code> holds…surprise, an error :D.</p>
+<p>The summary here is that Rust always know where there might be an error. And it force you to deal with it right where it appears (mostly). No hidden ones, no guessing, no breaking app with a surprise face.</p>
+<p>And this approach is just better. By A MILE.</p>
+<p>We cannot make TypeScript errors work like the Rust. The limiting factor here is the language itself; it doesn’t have the proper tools to do that.</p>
+<p>But what we can do is try to make it similar. And make it simple:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">type</span> <span class="title class_">Safe</span>&lt;T&gt; = </span><br><span class="line"> | &#123; </span><br><span class="line"> <span class="attr">success</span>: <span class="literal">true</span>; </span><br><span class="line"> <span class="attr">data</span>: T; </span><br><span class="line"> &#125; </span><br><span class="line"> | &#123; </span><br><span class="line"> <span class="attr">success</span>: <span class="literal">false</span>; </span><br><span class="line"> <span class="attr">error</span>: <span class="built_in">string</span>; </span><br><span class="line"> &#125;;</span><br></pre></td></tr></table></figure>
+
+<p>we do need a few try&#x2F;catches. The good thing is we only need about two, not 100,000:</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> safe&lt;T&gt;(<span class="attr">promise</span>: <span class="title class_">Promise</span>&lt;T&gt;, err?: <span class="built_in">string</span>): <span class="title class_">Promise</span>&lt;<span class="title class_">Safe</span>&lt;T&gt;&gt;;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> safe&lt;T&gt;(<span class="attr">func</span>: <span class="function">() =&gt;</span> T, err?: <span class="built_in">string</span>): <span class="title class_">Safe</span>&lt;T&gt;;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> safe&lt;T&gt;(</span><br><span class="line"> <span class="attr">promiseOrFunc</span>: <span class="title class_">Promise</span>&lt;T&gt; | (<span class="function">() =&gt;</span> T),</span><br><span class="line"> err?: <span class="built_in">string</span>,</span><br><span class="line">): <span class="title class_">Promise</span>&lt;<span class="title class_">Safe</span>&lt;T&gt;&gt; | <span class="title class_">Safe</span>&lt;T&gt; &#123;</span><br><span class="line"> <span class="keyword">if</span> (promiseOrFunc <span class="keyword">instanceof</span> <span class="title class_">Promise</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">safeAsync</span>(promiseOrFunc, err);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">safeSync</span>(promiseOrFunc, err);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> safeAsync&lt;T&gt;(</span><br><span class="line"> <span class="attr">promise</span>: <span class="title class_">Promise</span>&lt;T&gt;, </span><br><span class="line"> err?: <span class="built_in">string</span></span><br><span class="line">): <span class="title class_">Promise</span>&lt;<span class="title class_">Safe</span>&lt;T&gt;&gt; &#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> data = <span class="keyword">await</span> promise;</span><br><span class="line"> <span class="keyword">return</span> &#123; data, <span class="attr">success</span>: <span class="literal">true</span> &#125;;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(e);</span><br><span class="line"> <span class="keyword">if</span> (err !== <span class="literal">undefined</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123; <span class="attr">success</span>: <span class="literal">false</span>, <span class="attr">error</span>: err &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (e <span class="keyword">instanceof</span> <span class="title class_">Error</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123; <span class="attr">success</span>: <span class="literal">false</span>, <span class="attr">error</span>: e.<span class="property">message</span> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> &#123; <span class="attr">success</span>: <span class="literal">false</span>, <span class="attr">error</span>: <span class="string">&quot;Something went wrong&quot;</span> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> safeSync&lt;T&gt;(</span><br><span class="line"> <span class="attr">func</span>: <span class="function">() =&gt;</span> T, </span><br><span class="line"> err?: <span class="built_in">string</span></span><br><span class="line">): <span class="title class_">Safe</span>&lt;T&gt; &#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> data = <span class="title function_">func</span>();</span><br><span class="line"> <span class="keyword">return</span> &#123; data, <span class="attr">success</span>: <span class="literal">true</span> &#125;;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(e);</span><br><span class="line"> <span class="keyword">if</span> (err !== <span class="literal">undefined</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123; <span class="attr">success</span>: <span class="literal">false</span>, <span class="attr">error</span>: err &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (e <span class="keyword">instanceof</span> <span class="title class_">Error</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123; <span class="attr">success</span>: <span class="literal">false</span>, <span class="attr">error</span>: e.<span class="property">message</span> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> &#123; <span class="attr">success</span>: <span class="literal">false</span>, <span class="attr">error</span>: <span class="string">&quot;Something went wrong&quot;</span> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
+
+<p>This is just a wrapper with our <code>Safe</code> type as the return one. But sometimes simple things are all you need. Let’s combine them with the example from above.</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> request = &#123; <span class="attr">name</span>: “test”, <span class="attr">value</span>: <span class="number">2n</span> &#125;; </span><br><span class="line"><span class="keyword">const</span> body = <span class="title function_">safe</span>( </span><br><span class="line"> <span class="function">() =&gt;</span> <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(request), </span><br><span class="line"> “<span class="title class_">Failed</span> to serialize request”, </span><br><span class="line">); </span><br><span class="line"><span class="keyword">if</span> (!body.<span class="property">success</span>) &#123; </span><br><span class="line"> <span class="comment">// handle error (body.error) </span></span><br><span class="line"> <span class="keyword">return</span>; </span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">safe</span>( </span><br><span class="line"> <span class="title function_">fetch</span>(<span class="string">&quot;https://example.com&quot;</span>, &#123; </span><br><span class="line"> <span class="attr">method</span>: “<span class="variable constant_">POST</span>”, </span><br><span class="line"> <span class="attr">body</span>: body.<span class="property">data</span>, </span><br><span class="line"> &#125;), </span><br><span class="line">); </span><br><span class="line"><span class="keyword">if</span> (!response.<span class="property">success</span>) &#123; </span><br><span class="line"> <span class="comment">// handle error (response.error) </span></span><br><span class="line"> <span class="keyword">return</span>; </span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">if</span> (!response.<span class="property">data</span>.<span class="property">ok</span>) &#123; </span><br><span class="line"> <span class="comment">// handle network error </span></span><br><span class="line"> <span class="keyword">return</span>; </span><br><span class="line">&#125; </span><br><span class="line"><span class="comment">// handle response (body.data)</span></span><br></pre></td></tr></table></figure>
+
+<p>New solution is longer, but it performs better because of the following reasons:</p>
+<ul>
+<li>no try&#x2F;catch</li>
+<li>we handle each error where it occurs</li>
+<li>we can specify an error message for a specific function</li>
+<li>we have a nice top-to-bottom logic, all errors on top, then only the response at the bottom</li>
+</ul>
+
+</div>
+
+<script>
+ window.onload = detectors();
+</script>
+ <div class="post-footer">
+ <div class="h-line-primary"></div>
+ <nav class="post-nav">
+ <div class="prev-item">
+
+ <div class="icon arrow-left"></div>
+ <div class="post-link">
+ <a href="/2023/05/01/Rust-%E8%99%9A%E8%A1%A8%E5%B8%83%E5%B1%80%E8%A7%84%E5%88%99%E4%BB%8B%E7%BB%8D/">Prev</a>
+ </div>
+
+ </div>
+ <div class="next-item">
+
+ <div class="icon arrow-right"></div>
+ <div class="post-link">
+ <a href="/2023/04/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%9B%9B%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">Next</a>
+ </div>
+
+ </div>
+ </nav>
+</div>
+
+
+ <div class="post-comment">
+
+
+
+
+
+
+
+</div>
+
+
+</article>
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+ </div>
+
+
+ <div class="search-popup">
+ <div class="search-popup-overlay">
+ </div>
+ <div class="search-popup-window" >
+ <div class="search-header">
+ <div class="search-input-container">
+ <input autocomplete="off" autocapitalize="off" maxlength="80"
+ placeholder="Search Anything" spellcheck="false"
+ type="search" class="search-input">
+ </div>
+ <div class="search-close-btn">
+ <div class="icon close-btn"></div>
+ </div>
+ </div>
+ <div class="search-result-container">
+ </div>
+ </div>
+</div>
+
+<script>
+ const searchConfig = {
+ path : "/search.xml",
+ top_n_per_article: "1",
+ unescape : "false",
+ trigger: "auto",
+ preload: "false"
+ }
+</script>
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
+<script src="/js/search.js"></script>
+
+
+
+ </body>
+</html>