<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Simon Cheng</title>
    <description>Building reliable web products with clean engineering.</description>
    <link>https://codersimonchan.github.io/</link>
    <atom:link href="https://codersimonchan.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 16 Jul 2026 14:14:54 +0000</pubDate>
    <lastBuildDate>Thu, 16 Jul 2026 14:14:54 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>How Callback Works</title>
        <description>&lt;h1 id=&quot;understanding-callback-functions-in-javascript-made-simple&quot;&gt;Understanding Callback Functions in JavaScript (Made Simple)&lt;/h1&gt;

&lt;p&gt;When people first hear about &lt;strong&gt;callback functions&lt;/strong&gt;, they often get confused. The term sounds fancy, but the concept is actually straightforward once you break it down. Let’s go step by step.&lt;/p&gt;

&lt;hr /&gt;

&lt;ol&gt;
  &lt;li&gt;What Is a Callback Function?&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;A &lt;strong&gt;callback function&lt;/strong&gt; is simply a function that you &lt;strong&gt;pass as an argument&lt;/strong&gt; to another function. The receiving function can then &lt;strong&gt;decide when to call (or “call back”) that function&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 Think of it like giving someone your phone number. They’re not calling you right away. Instead, you’re saying:&lt;br /&gt;
&lt;em&gt;“Here’s my number. Call me back later when you have news.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s exactly what a callback is in programming:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;You pass a function (your phone number).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The other function saves it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It “calls back” that function at the right time.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;ol&gt;
  &lt;li&gt;Passing Functions as Arguments&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;In JavaScript, functions are &lt;strong&gt;first-class citizens&lt;/strong&gt;. This means you can treat them like any other variable — you can assign them to variables, pass them around, and use them as arguments.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function greet(name) {
  console.log(&quot;Hello, &quot; + name);
}

function processUserInput(callback) {
  const name = &quot;Alice&quot;;
  callback(name);  // call the function passed in
}

processUserInput(greet);
// Output: Hello, Alice

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Here, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;greet&lt;/code&gt; is not executed immediately when we pass it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;processUserInput&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Instead, its &lt;strong&gt;reference&lt;/strong&gt; is passed (basically, the memory address where the function lives).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Later, inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;processUserInput&lt;/code&gt;, the function gets invoked with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback(name)&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;ol&gt;
  &lt;li&gt;Regular Functions vs Callback Functions&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;You can think about it like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Regular function&lt;/strong&gt; → Takes data as input and always applies the &lt;em&gt;same method&lt;/em&gt; to process it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Callback function&lt;/strong&gt; → Lets you change the &lt;em&gt;method itself&lt;/em&gt;. You’re basically passing an &lt;em&gt;algorithm&lt;/em&gt; (a function) into another function, so the same data can be processed in different ways.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function processNumbers(numbers, callback) {
  return numbers.map(callback);
}

const numbers = [1, 2, 3];

// Double each number
console.log(processNumbers(numbers, num =&amp;gt; num * 2));
// [2, 4, 6]

// Square each number
console.log(processNumbers(numbers, num =&amp;gt; num * num));
// [1, 4, 9]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, the same data (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;numbers&lt;/code&gt;) is processed differently depending on which callback you provide.&lt;/p&gt;

&lt;hr /&gt;

&lt;ol&gt;
  &lt;li&gt;Why Do We Need Callbacks?&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;The &lt;strong&gt;real power&lt;/strong&gt; of callbacks comes with &lt;strong&gt;asynchronous operations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;JavaScript is single-threaded — it can’t do everything at once. But things like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Reading a file,&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Making a network request,&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Querying a database,&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;all take time. If the program paused and waited for these to finish, everything would freeze!&lt;/p&gt;

&lt;p&gt;Instead, JavaScript says:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;“I’ll start this operation.”&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;“When it’s done, I’ll &lt;strong&gt;call back&lt;/strong&gt; the function you gave me.”&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s how we achieve &lt;strong&gt;non-blocking, delayed execution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example with&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;console.log(&quot;Start&quot;);

setTimeout(() =&amp;gt; {
  console.log(&quot;This runs later!&quot;);
}, 2000);

console.log(&quot;End&quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Start
End
This runs later!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice how the callback inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout&lt;/code&gt; only runs &lt;strong&gt;after 2 seconds&lt;/strong&gt; — not immediately.&lt;/p&gt;

&lt;hr /&gt;

&lt;ol&gt;
  &lt;li&gt;Key Point: Reference vs Execution&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;When you pass a function as an argument, you’re passing its &lt;strong&gt;reference&lt;/strong&gt;, not its &lt;strong&gt;result&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By passing the reference, the receiving function gets control over &lt;strong&gt;when&lt;/strong&gt; to execute it.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;Callbacks may seem tricky at first, but they’re just functions passed around like variables. The magic happens because the receiving function can &lt;strong&gt;choose when&lt;/strong&gt; to run them — immediately, later, or only if certain conditions are met.&lt;/p&gt;

&lt;p&gt;Once you really get this idea, you’ll see callbacks everywhere in JavaScript — and you’ll understand why they’re such an important building block for async programming.&lt;/p&gt;

&lt;hr /&gt;
</description>
        <pubDate>Sun, 17 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://codersimonchan.github.io/2025/08/callback/</link>
        <guid isPermaLink="true">https://codersimonchan.github.io/2025/08/callback/</guid>
        
        <category>JS</category>
        
        
      </item>
    
      <item>
        <title>How Event Loop Works</title>
        <description>&lt;h2 id=&quot;what-is-event-loop&quot;&gt;What is event loop&lt;/h2&gt;

&lt;p&gt;The Event Loop is an important concept in JavaScript runtime environments, particularly in browsers and Node.js. It manages the execution order of asynchronous operations, callback functions, and events. We could say event loop is actually a mechanism , with this mechanism enables JavaScript to handle asynchronous operations within a single thread while maintaining relatively good performance and responsiveness.&lt;/p&gt;

&lt;p&gt;Although there are some differences in the event loop between Node.js and browsers, the core concept remains similar. Understanding the event loop is crucial for writing efficient, non-blocking JavaScript code, especially when dealing with numerous I/O operations and asynchronous tasks.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;file:///C:/ITDevSimon/github/codehub/images/posts/jekyll/eventloop.png&quot; alt=&quot;eventloop&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-event-loop-works&quot;&gt;How Event Loop works&lt;/h2&gt;

&lt;p&gt;When running an program in browser, the computer not only help us create a heap and call stack for us, where we used running our code, we can also call it main thread, but also create two queues, one of them is Web API, another is Event Queue, and task queue and microtask queue are included in Event Queue.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Web API&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Event Queue: for all those asynchronous task should be in event queue, waiting to be called&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;macro task queue&lt;/li&gt;
      &lt;li&gt;microtask queue
    1. First of all, main thread would execute the code from top to bottom, if meet any asynchronous task, just put it into Web API to monitor, will not prevent the main thread to run the synchronous code from top to bottom.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;When any monitored asynchronous task in WEB API is ready to run, it won’t execute immediately, instead was moved to Event Queue to wait to be called.&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;There are 2 queues in Event Queue depends on micro task or macro task (task)&lt;/li&gt;
      &lt;li&gt;First-In-First-Out, who first comes into the queue would be first called in their own task queue.&lt;/li&gt;
      &lt;li&gt;So, for many timer tasks, we do set up a timer. However, when the  scheduled time is reached, it doesn’t necessarily run immediately. The  scheduled time merely places the task in the queue, waiting its turn,  rather than executing it immediately.&lt;/li&gt;
      &lt;li&gt;Microtasks always take priority over macro tasks&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When all synchronous tasks have been executed and completed, the main thread becomes available. The microtask queue is then processed on the main thread if there are microtasks in the micro queue, they are executed one by one. If there are no microtasks, the event loop checks for any pending macro tasks in the task queue and executes them. After processing one macro tasks, the event loop returns to the microtask queue to check if there are any remaining microtasks. This emphasizes that microtasks always take priority over macro tasks. Macro tasks are executed only when the microtask queue is empty. For those tasks of the same level are processed in a first-in-first-out manner.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;micro-or-macro&quot;&gt;Micro or Macro&lt;/h2&gt;

&lt;h3 id=&quot;macro-tasks-macrotasks&quot;&gt;&lt;strong&gt;Macro tasks (Macrotasks):&lt;/strong&gt;&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setInterval&lt;/code&gt;: Timer tasks.&lt;/li&gt;
  &lt;li&gt;I/O operations: Such as file read/write, network requests.&lt;/li&gt;
  &lt;li&gt;Page rendering: Updating DOM elements.&lt;/li&gt;
  &lt;li&gt;User interaction events: Clicks, inputs, etc.&lt;/li&gt;
  &lt;li&gt;Event callbacks: Handling event listeners.&lt;/li&gt;
  &lt;li&gt;Request animation frame: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestAnimationFrame&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;micro-tasks-microtasks&quot;&gt;&lt;strong&gt;Micro tasks (Microtasks):&lt;/strong&gt;&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Promise&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt;: Handling the results of Promise objects.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async/await&lt;/code&gt;: Code following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; is treated as a microtask after the Promise is resolved.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MutationObserver&lt;/code&gt;: Observing DOM changes.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queueMicrotask&lt;/code&gt;: Adding a task to the microtask queue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Key points to note:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Micro tasks are executed immediately after the current macro task finishes. They have a higher priority.&lt;/li&gt;
  &lt;li&gt;Micro tasks are commonly used to handle Promise results and other tasks that need to be executed as soon as possible within the current event loop.&lt;/li&gt;
  &lt;li&gt;Macro tasks are executed after micro tasks, only when the current task queue is empty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please keep in mind that the list provided is not exhaustive, and the specific macro tasks and micro tasks may vary depending on the JavaScript runtime environment (such as browsers, Node.js). Understanding the execution order of macro tasks and micro tasks is crucial for writing effective asynchronous code.&lt;/p&gt;

&lt;h3 id=&quot;reference&quot;&gt;Reference&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif&quot;&gt;https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 19 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://codersimonchan.github.io/2023/08/eventloop/</link>
        <guid isPermaLink="true">https://codersimonchan.github.io/2023/08/eventloop/</guid>
        
        <category>JS</category>
        
        
      </item>
    
      <item>
        <title>English</title>
        <description>&lt;p&gt;[TOC]&lt;/p&gt;
&lt;h1 id=&quot;english-at-work&quot;&gt;English at work&lt;/h1&gt;

&lt;p&gt;English at work is aim to help you to improve the efficiency and ability in the communication at work. Save you much time to understand what is really need at work. Sometimes a  good communication is really necessary and important for solving a challenging problem.&lt;/p&gt;

&lt;p&gt;表示目前还不理解，详细研究之后，有问题再问&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I&apos;m not quite clear on this issue yet. I would like to examine it more closely, and if I have any further questions, I&apos;ll get back to you
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;表示你会调查问题并尽快回复对方。这句话传达了你对问题的关注，并表示你会尽快提供答复或解决方案&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I will look into the issue and get back to you ASAP.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们稍后联系，讨论细节。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Let&apos;s touch base later to discuss the details.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我会调查并给您提供一个解决方案&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I&apos;ll look into that and get back to you with a solution.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;请问能否给我提供一下项目的最新进展？&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Could you please provide me with an update on the project?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们需要在截止日期前完成，所以让我们根据任务的优先级进行安排&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;We need to meet the deadline, so let&apos;s prioritize our tasks accordingly.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我正在处理另一个项目，但我会抽出时间帮助您处理您的请求。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I&apos;m currently working on another project, but I&apos;ll make time to assist you with your request.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;让我们安排一个会议，详细讨论此事&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Let&apos;s schedule a meeting to discuss this matter in more detail.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们面临一些技术问题，但我们正在积极解决&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;We&apos;re facing some technical issues, but we&apos;re actively working on resolving them.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我将在今天结束前发送给您报告&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I&apos;ll send you the report by the end of the day.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;让我们在团队会议上集思广益，为即将到来的项目提出创意。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Let&apos;s brainstorm ideas for the upcoming project during our team meeting.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;技术上可行，但不确定业务上是否可行&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Technically possible but uncertain in terms of business logic.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我有些大概的想法&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I have some rough ideas on this.I&apos;d love to hear your thoughts on this
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我发现/觉得这个有点难度&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I&apos;m finding it really challenging
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The vast majority(大多数) of React projects will use the JSX code and build process that transforms it. Nonetheless(虽热如此), you should know that you technically don’t need JSX&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;什么是 RESTful API？它的特点是什么？&lt;/p&gt;

    &lt;p&gt;Separate API into logical resources, endpoints should be resources_based(nouns) and use HTTP methods for actions. and also is stateless, all state is handled on the client. This means that each request must contain all the information necessary to process a certain request. The server should not have to remember previous requests. and usually send data as JSON.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释一下数据库事务，并说明在什么情况下应该使用事务。&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;When you need to complete multiple operations together, ensuring that they either all succeed or all get rolled back.&lt;/li&gt;
      &lt;li&gt;When multiple people are accessing the database simultaneously, using a transaction can prevent data from getting messed up.&lt;/li&gt;
      &lt;li&gt;When you need to make sure complex operations or business logic either fully take effect or fully get canceled.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;In short, a database transaction is a way to ensure the correctness of database operations, like a secure set of actions that either happen together or don’t happen at all. This ensures data consistency and reliability.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释关系型数据库和非关系型数据库的区别，并提供一些常见的示例。&lt;/p&gt;

    &lt;p&gt;Support for strict data consistency and transaction processing, suitable for complex relational data. Suitable for applications requiring high consistency and strong transaction support, such as financial systems and enterprise-level applications.(MySQL,Oracle,SQL Server)&lt;/p&gt;

    &lt;p&gt;Support for higher scalability, suitable for large-scale distributed systems. In some cases, they sacrifice consistency for better performance and availability. Suitable for applications requiring handling large volumes of data and high concurrency, such as social media and big data analytics.（MongoDB，Redis）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;什么是索引？为什么在数据库表中使用索引是有益的？&lt;/p&gt;

    &lt;p&gt;An index in a database is a data structure that enhances the speed of data retrieval from a database table. Think of an index as a table of contents in a book – it provides a quick way to locate data without having to scan the entire table. Using indexes in database tables is beneficial for several reasons:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;strong&gt;Accelerated Data Retrieval:&lt;/strong&gt; Indexes can significantly speed up data retrieval. By creating indexes on columns, the database can quickly locate rows that match specific conditions without scanning the entire table.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Reduced Query Cost:&lt;/strong&gt; Indexes lessen the workload required for queries, especially in large tables. They can notably decrease the time complexity of queries, thus improving the responsiveness of the database system.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Optimized Sorting and Grouping:&lt;/strong&gt; Indexes enhance the efficiency of sorting and grouping operations. The database can use indexes to avoid sorting or grouping the entire table, focusing only on the indexed data.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Faster Join Operations:&lt;/strong&gt; Indexes expedite join operations when multiple tables are involved. They allow the database to swiftly locate rows that match join conditions, reducing the time taken for join operations.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Enforced Uniqueness:&lt;/strong&gt; In some cases, unique indexes can be created on columns to enforce data uniqueness. This prevents duplicate data from entering the table.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;In conclusion, using indexes in database tables can significantly enhance query performance, but it’s important to weigh the pros and cons, select appropriate columns for indexing, and ensure efficient database operation based on the specific context.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释一下 REST 和 SOAP 的区别。&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;REST (Representational State Transfer):&lt;/strong&gt; REST is an architectural style based on resources, emphasizing organizing and accessing data in a manner similar to resources on the web. Each resource is uniquely identified by a URL, and standard HTTP methods (GET, POST, PUT, DELETE, etc.) are used to access and manipulate them. REST services commonly use data formats like JSON or XML.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;SOAP (Simple Object Access Protocol):&lt;/strong&gt; SOAP is a protocol designed to support communication between different systems. It defines a standardized message format and communication pattern, facilitating interaction between different platforms and programming languages. SOAP messages are often enveloped within the body of HTTP or other protocol messages and typically use XML for structuring data.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Transmission:&lt;/strong&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;REST commonly employs native HTTP methods for communication, while SOAP messages are typically transferred via HTTP, SMTP, or other protocols. SOAP messages are wrapped within HTTP or other protocol messages.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;&lt;strong&gt;Data Format:&lt;/strong&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;REST often uses JSON for data exchange due to its lightweight nature and readability.&lt;/li&gt;
      &lt;li&gt;SOAP uses XML to encapsulate data with well-defined structures and tags.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;&lt;strong&gt;State Management:&lt;/strong&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;REST is stateless, requiring each request to carry enough context information for the server to understand it. State is usually maintained on the client side.&lt;/li&gt;
      &lt;li&gt;SOAP can manage state using various mechanisms, potentially retaining some state information during communication.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;&lt;strong&gt;Flexibility and Complexity:&lt;/strong&gt;&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;REST is simpler and more flexible, making it well-suited for lightweight and mobile applications. It’s typically easier to implement and maintain.&lt;/li&gt;
      &lt;li&gt;SOAP offers greater functionality and security, making it suitable for complex enterprise applications and integration scenarios. However, it’s also more complex and heavyweight.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;什么是微服务架构？它有哪些优点和缺点？&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释一下负载均衡是如何工作的，并提供一些常见的负载均衡算法。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;什么是哈希表（Hash Table）？它在算法和数据结构中的作用是什么？&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释一下分布式系统的概念，并说明它与单机系统的区别。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释一下消息队列的概念，并说明它在应用程序开发中的作用。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;什么是反向代理？它与正向代理有何区别？&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释一下 OAuth 2.0 的工作原理，并说明它在身份验证和授权中的应用。&lt;/p&gt;

    &lt;p&gt;https://zhuanlan.zhihu.com/p/92051359&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释一下 SQL 注入攻击是如何发生的，以及如何防止它。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;什么是缓存？请描述一下缓存的工作原理，并说明在应用程序中使用缓存的优点。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;请解释一下面向对象编程（Object-Oriented Programming）的概念，并说明它的核心原则。
这些问题涵盖了后端开发中的一些基本概念和常见话题。确保你理解每个问题，并能够清晰地表达你的答案。此外，还要准备其他与你所申请的职位相关的问题，以便在面试过程中展示你的技能和经验。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Tue, 01 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://codersimonchan.github.io/2023/08/english/</link>
        <guid isPermaLink="true">https://codersimonchan.github.io/2023/08/english/</guid>
        
        <category>Language</category>
        
        
      </item>
    
      <item>
        <title>An utility function that wraps async functions to handle errors</title>
        <description>&lt;h2 id=&quot;handle-errors-with-trycatch&quot;&gt;Handle errors with try…catch&lt;/h2&gt;

&lt;p&gt;In Node.js, you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try...catch&lt;/code&gt; blocks to handle exceptions (errors) that might occur during the execution of your code. When using an async function, you’ll notice that await only captures the value of a successful promise, making it unable to capture the failure results of the catch method execution. As a result, in async functions, we commonly employ the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try...catch&lt;/code&gt; structure to handle errors. Whenever an error occurs within the try block, the code execution pauses, and the catch block captures the error. Hence, it’s a common practice to combine async functions with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try...catch&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;catchasync-function&quot;&gt;CatchAsync function&lt;/h2&gt;

&lt;p&gt;However, utilizing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try...catch&lt;/code&gt; structure within each individual async function can be cumbersome and lead to messy code structure. To address this, we can create a catchAsync function that wraps and captures errors for asynchronous functions.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module.exports = fn =&amp;gt; {       
    return (req, res, next)=&amp;gt;{ 
        fn(req, res, next).catch(next);  
    };
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In above: catch(next)  === catch(err =&amp;gt; next(err))&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module.exports = fn =&amp;gt; {       
    return (req, res, next)=&amp;gt;{ 
        fn(req, res, next).catch(err =&amp;gt; next(err));  
    };
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;1.&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;module.exports&lt;/code&gt;: This is a Node.js construct used to export functionality from a module. In this case, the module is exporting a function.&lt;/p&gt;

&lt;p&gt;2.&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(req, res, next) =&amp;gt; { ... }&lt;/code&gt;: This is an Express.js middleware function. It takes three arguments: req (request), res (response), and next (next is actually a function in the chain). It wraps the async function and handles any errors that may occur.&lt;/p&gt;

&lt;p&gt;3.&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn(req, res, next)&lt;/code&gt;: This line executes the original async function (fn) and passes the request, response, and next middleware function to it.&lt;/p&gt;

&lt;p&gt;4.&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.catch(err =&amp;gt; next(err))&lt;/code&gt;: This is where the error handling takes place. If the async function’s promise rejects (throws an error), the .catch block captures the error (err) and passes it to the next middleware function,  it will trigger the error-handling middleware rather than proceeding to the next regular middleware in the chain.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In summary, the module.exports code defines a utility function that wraps async functions to handle errors and pass them to the next middleware. This can be used in an Express.js application to simplify error handling in asynchronous routes and middleware. To use this utility, you can require it in your code and apply it to your async route or middleware functions.&lt;/p&gt;
</description>
        <pubDate>Sat, 29 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://codersimonchan.github.io/2023/07/catchAsyncError/</link>
        <guid isPermaLink="true">https://codersimonchan.github.io/2023/07/catchAsyncError/</guid>
        
        <category>JS</category>
        
        
      </item>
    
      <item>
        <title>Parallel and series in JavaScript</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://juejin.cn/post/7136084613075730469&quot;&gt;参考文档&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;promise的并行&quot;&gt;promise的并行&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;array.map( function(currentElement, index, arr){} )  ： map() creates a new array from calling a function for every array element.&lt;/li&gt;
  &lt;li&gt;当只有第一个参数currentElement的时候，可以写成箭头函数的形式 map（t =&amp;gt; {return }）， 此处涉及到箭头函数简写 t =&amp;gt; {return } 。&lt;/li&gt;
  &lt;li&gt;函数通过为数组每一个element调用一个函数，将计算结果返回一个新的数组，在上例子中， map（t =&amp;gt; { return ()=&amp;gt;{ return } ）,在map调用的函数当中，返回一个函数(函数会返回函数)&lt;/li&gt;
  &lt;li&gt;会返回一个新的函数放进数组当中，并且这些新的函数会返回一个promise，此时fnarr是一个新的函数数组，这样可以用fnarr数组再次调用map函数时，就会调用fnarr数组的元素本身（因为此时元素本身就是一个函数）&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fnarr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;fnarr 是一个包含多个函数的数组，每个函数返回一个 Promise 对象。当使用 map 方法对 fnarr 进行遍历，并对每个函数执行调用 fn()，返回一个 Promise 对象的数组。然后，使用 Promise.all 方法来等待所有的 Promise 对象完成。一旦所有的 Promise 对象都解析（成功），then 方法中的回调函数将会被执行，并接收一个包含所有 Promise 解析值的数组 resArr。
可以看到，尽管所有的Promise是并行执行的，但是在promise当中打印返回的结果是按照顺序排列的，这一点在某些场景下很有用。&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fnarr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resArr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resArr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;打印结果:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 0s后
promise0
// 1s后
promise1
// 2s后
promise2
// 3s后
promise3
// 4s后
promise4
// 5s后
promise5
// 当所有promise执行完后返回所有的结果
[0, 1, 2, 3, 4, 5]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;promise的串行&quot;&gt;promise的串行&lt;/h2&gt;

&lt;p&gt;既然要求串行，首先想到的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async/await&lt;/code&gt;实现:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;async function run() {
  for (let i = 0; i &amp;lt; fnarr.length; i++) {
    const result = await fnarr[i]()
    console.log(i, result)
  }
}

run()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;打印结果：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 0s后
0 0
// 1s后
1 1
// 2s后
2 2
// 3s后
3 3
// 4s后
4 4
// 5s后
5 5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;promise的串行和并行&quot;&gt;promise的串行和并行&lt;/h2&gt;

&lt;p&gt;利用上面的知识，我们现在有一个需求：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;可以并发发送请求；这样代码在多个异步处理之后一起执行，而不是一个一个去执行。&lt;/li&gt;
  &lt;li&gt;可以控制并发的数量：就是先发几个请求等这几个请求的结果回来后，在发另外的请求；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;思路：并发可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Promise.all&lt;/code&gt;，而控制并发的数量，相当于是串行，可以使用async+await来做。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1.分组：把所有的请求按照并发数量进行分组
2.分组之后，那么就一组一组地按照顺序执行，即串行，使用async+await
3.将request分组，小组与小组之间是串行，而组内请求是并行
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;组间串行&quot;&gt;组间串行&lt;/h3&gt;

&lt;p&gt;首先分组，把所有的请求按照并发数量进行分组,这个函数可以将一个数组按照指定的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max&lt;/code&gt;大小进行分组，返回一个新的二维数组，其中每个子数组最多包含&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max&lt;/code&gt;个元素。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const group = (list = [], max = 0) =&amp;gt; {
  if (!list.length) {
    return list;
  }
  let results = [];
  for (let i = 0, len = list.length; i &amp;lt; len; i += max) {
    results.push(list.slice(i, i + max));
  }
  return results;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;组内并行&quot;&gt;组内并行&lt;/h3&gt;

&lt;p&gt;分组之后，那么就一组一组的执行，即串行，使用async+await&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;async function sendRequest(requests = [], max = 0, callback = () =&amp;gt; {}) {
  if (!requests.length) {
    return requests
  }
  const groupRequest = group(requests, max)
  const results = []
  // groupItems是一个小组，groupRequst是所有的小组，这样让小组与小组之间的请求是串行，而组内的请求是并行的。
  for (let groupItems of groupRequest) {
    const result = await requestHandler(groupItems, callback) //组内并行，组间串行
    results.push(result)
  }
  console.log(&apos;done&apos;, results)
  return results
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;groupItems是一个小组，小组内并行&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;async function requestHandler(groupItems, callback = () =&amp;gt; {}) {
  if (!groupItems.length) {
    callback()
    return groupItems
  }
  const promiseArr = groupItems.map(fn =&amp;gt; fn())
  const data = await Promise.allSettled(promiseArr).then(resArr =&amp;gt; {
    resArr.map(callback)//这里callback，等待输入函数，输入的函数可以打印所有的promise的value的值
    return resArr
  })
  return data
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const p1 = () =&amp;gt; new Promise((resolve, reject) =&amp;gt; setTimeout(resolve, 1000, &apos;p1&apos;))
const p2 = () =&amp;gt; Promise.resolve(&apos;p2&apos;)
const p3 = () =&amp;gt; new Promise((resolve, reject) =&amp;gt; setTimeout(resolve, 2000, &apos;p3&apos;))
const p4 = () =&amp;gt; Promise.resolve(&apos;p4&apos;)
const p5 = () =&amp;gt; new Promise((resolve, reject) =&amp;gt; setTimeout(resolve, 2000, &apos;p5&apos;))
const p6 = () =&amp;gt; Promise.resolve(&apos;p6&apos;)
const p7 = () =&amp;gt; new Promise((resolve, reject) =&amp;gt; setTimeout(resolve, 1000, &apos;p7&apos;))
const p8 = () =&amp;gt; Promise.resolve(&apos;p8&apos;)
const p9 = () =&amp;gt; new Promise((resolve, reject) =&amp;gt; setTimeout(reject, 1000, &apos;p9&apos;))

const arr = [p1, p2, p3, p4, p5, p6, p7, p8, p9]

sendRequest(arr, 3, ({ reason, value }) =&amp;gt; {
    console.log(value || reason)
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;打印结果:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 3个为一组，每组都必须要请求结束
p1
p2
p3
// 3个为一组，每组都必须要请求结束
p4
p5
p6
// 3个为一组，每组都必须要请求结束
p7
p8
p9
// 最后的结果result
done [
  [
    { status: &apos;fulfilled&apos;, value: &apos;p1&apos; },
    { status: &apos;fulfilled&apos;, value: &apos;p2&apos; },
    { status: &apos;fulfilled&apos;, value: &apos;p3&apos; }
  ],
  [
    { status: &apos;fulfilled&apos;, value: &apos;p4&apos; },
    { status: &apos;fulfilled&apos;, value: &apos;p5&apos; },
    { status: &apos;fulfilled&apos;, value: &apos;p6&apos; }
  ],
  [
    { status: &apos;fulfilled&apos;, value: &apos;p7&apos; },
    { status: &apos;fulfilled&apos;, value: &apos;p8&apos; },
    { status: &apos;rejected&apos;, reason: &apos;p9&apos; }
  ]
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Promise.allSettled&lt;/code&gt;是一个新的API，跟&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Promise.all&lt;/code&gt;差不多的用法，也是接受的数组，不过不同的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Promise.allSettled&lt;/code&gt;会等所有任务结束之后才会返回结果，而&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Promise.all&lt;/code&gt;只要有一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reject&lt;/code&gt;就会返回结果。&lt;/p&gt;

&lt;p&gt;同时&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Promise.allSettled&lt;/code&gt;返回的结果也有些不同：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;如果对应的 promise 已经 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fulfilled&lt;/code&gt;，返回 { status: ‘fulfilled’, value: value }&lt;/li&gt;
  &lt;li&gt;如果相应的 promise 已经被 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rejected&lt;/code&gt;，返回 {status: ‘rejected’， reason: reason }&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PS： setTimeout第三个参数的作用是给回调函数传入参数，如下&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for (var i = 0; i&amp;lt;4; i++) {
  setTimeout((i) =&amp;gt; {
    console.log(i)
  }, 1000, i)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;PS：Async.js (https://caolan.github.io/async/)：Async.js是一个功能强大的实用工具库，提供了许多用于处理异步JavaScript的函数。它包括&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async.series&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async.parallel&lt;/code&gt;等函数，可用于按顺序或并行执行任务。&lt;/p&gt;
</description>
        <pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://codersimonchan.github.io/2023/07/try-catch/</link>
        <guid isPermaLink="true">https://codersimonchan.github.io/2023/07/try-catch/</guid>
        
        <category>JS</category>
        
        
      </item>
    
      <item>
        <title>How to debug NodeJS</title>
        <description>&lt;h2 id=&quot;default-debugging-process&quot;&gt;Default debugging process&lt;/h2&gt;

&lt;p&gt;The default debugging process of NodeJS (read Node.js) is quite clumsy. You are likely already aware of the need to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--inspect&lt;/code&gt; to the node script with node inspector. It is also dependent on Chrome. Then you have to look at the proper web socket connection which is hard, and debug using Chrome’s node debugger. To be honest, it is a pain in the neck.&lt;/p&gt;

&lt;p&gt;Finally, Google chrome labs has released ndb, which they say is “An improved debugging experience for Node.js, enabled by Chrome DevTools”. Ndb is a boon when debugging a Nodejs app.&lt;/p&gt;

&lt;h3 id=&quot;1-getting-started-install-ndb&quot;&gt;1. Getting started, install ndb&lt;/h3&gt;

&lt;p&gt;Installing ndb is very easy. All you need to do to get started debugging your nodejs application is to install &lt;a href=&quot;https://github.com/GoogleChromeLabs/ndb#installation&quot;&gt;ndb&lt;/a&gt;. I would suggest that you install it globally with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm i ndb –save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also install and use it locally per app if you want. One thing I had to fix was to get the latest version of Chrome, as I saw some permission issues.&lt;/p&gt;

&lt;h3 id=&quot;2-run-the-app-with-ndb-not-node-or-nodemon&quot;&gt;2. Run the app with ndb (not node or nodemon)&lt;/h3&gt;

&lt;p&gt;For debugging nodejs applications with ndb, you can directly run the nodejs app script with ndb rather than node. For example, if you were used to doing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node index.js&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nodemon index.js&lt;/code&gt; in development. To debug your app you can run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;scripts&quot;: {
  &quot;debug&quot;: &quot;ndb app.js&quot;
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ndb app.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that you don’t need to put any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-- inspect&lt;/code&gt; so the experience is a lot smoother. You don’t need to remember a different port or go to chrome devtools and open up a different inspector window to debug. Such a relief!&lt;/p&gt;

&lt;p&gt;ndb opens up a screen like below when you do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ndb .&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ndb index.js&lt;/code&gt;
&lt;img src=&quot;/images/posts/jekyll/breakpoint.png&quot; alt=&quot;eventloop&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Please add a breakpoint on line 46. As you have run the application with ndb it will run in debug mode and stop at the breakpoint like below when you hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:8080/api/convert/USD/AUD/2019-01-01&lt;/code&gt; on the browser.&lt;/p&gt;

&lt;p&gt;ndb allows you to run any script for debugging. For example, I can run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ndb npm start&lt;/code&gt; and it will use the nodemon run. This means I can debug the application while changing the code which is great.&lt;/p&gt;

&lt;p&gt;As an example it can be run with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ndb npm start&lt;/code&gt; to debug this NodeJS express application.&lt;/p&gt;

&lt;h3 id=&quot;3-lets-debug-some-code&quot;&gt;3. Let’s debug some code&lt;/h3&gt;

&lt;h3 id=&quot;reference&quot;&gt;Reference&lt;/h3&gt;

&lt;p&gt;https://www.freecodecamp.org/news/how-to-get-started-debugging-nodejs-applications-with-ndb-a37e8747dbba/&lt;/p&gt;
</description>
        <pubDate>Wed, 18 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://codersimonchan.github.io/2023/01/debugging-NodeJS/</link>
        <guid isPermaLink="true">https://codersimonchan.github.io/2023/01/debugging-NodeJS/</guid>
        
        <category>JS</category>
        
        
      </item>
    
  </channel>
</rss>
