<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Usubeni Fantasy HN branch]]></title><description><![CDATA[Usubeni Fantasy HN branch]]></description><link>https://hn.ssshooter.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 06:54:32 GMT</lastBuildDate><atom:link href="https://hn.ssshooter.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to cancel Ajax? Do you need to cancel it?]]></title><description><![CDATA[Ajax cancel
If you are familiar with xhr, you know that Ajax can be canceled in front end using XMLHttpRequest.abort(). Of course, this is not the era of slash-and-burn cultivation. Except for interviews, no body makes you to write xhr from from scra...]]></description><link>https://hn.ssshooter.com/how-to-cancel-ajax-do-you-need-to-cancel-it</link><guid isPermaLink="true">https://hn.ssshooter.com/how-to-cancel-ajax-do-you-need-to-cancel-it</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Ajax]]></category><category><![CDATA[AbortController]]></category><dc:creator><![CDATA[DJJo]]></dc:creator><pubDate>Mon, 01 Aug 2022 08:18:23 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-ajax-cancel">Ajax cancel</h2>
<p>If you are familiar with <code>xhr</code>, you know that Ajax can be canceled in front end using <code>XMLHttpRequest.abort()</code>. Of course, this is not the era of slash-and-burn cultivation. Except for interviews, no body makes you to write <code>xhr</code> from from scratch. For the ubiquitous axios, there two ways to cancel ajax:</p>
<p>The first way is the old-fashioned <code>CancelToken</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> CancelToken = axios.CancelToken
<span class="hljs-keyword">const</span> source = CancelToken.source()

axios
  .get(<span class="hljs-string">'/user/12345'</span>, {
    <span class="hljs-attr">cancelToken</span>: source.token,
  })
  .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">thrown</span>) </span>{
    <span class="hljs-keyword">if</span> (axios.isCancel(thrown)) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Request canceled'</span>, thrown.message)
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-comment">// handle error</span>
    }
  })

axios.post(
  <span class="hljs-string">'/user/12345'</span>,
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">'new name'</span>,
  },
  {
    <span class="hljs-attr">cancelToken</span>: source.token,
  }
)

<span class="hljs-comment">// cancel the request (the message parameter is optional)</span>
source.cancel(<span class="hljs-string">'Operation canceled by the user.'</span>)
</code></pre>
<p>And the second way is the new (not really new in fact) <code>AbortController</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> controller = <span class="hljs-keyword">new</span> AbortController()

axios
  .get(<span class="hljs-string">'/foo/bar'</span>, {
    <span class="hljs-attr">signal</span>: controller.signal,
  })
  .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">response</span>) </span>{
    <span class="hljs-comment">//...</span>
  })
<span class="hljs-comment">// cancel the request</span>
controller.abort()
</code></pre>
<p>No matter you use <code>AbortController</code> or <code>CancelToken</code>, axios will execute <code>XMLHttpRequest.abort()</code> under the hood.</p>
<pre><code class="lang-javascript">onCanceled = <span class="hljs-function">(<span class="hljs-params">cancel</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (!request) {
    <span class="hljs-keyword">return</span>
  }
  reject(
    !cancel || cancel.type ? <span class="hljs-keyword">new</span> CanceledError(<span class="hljs-literal">null</span>, config, request) : cancel
  )
  request.abort()
  request = <span class="hljs-literal">null</span>
}

config.cancelToken &amp;&amp; config.cancelToken.subscribe(onCanceled)
<span class="hljs-keyword">if</span> (config.signal) {
  config.signal.aborted
    ? onCanceled()
    : config.signal.addEventListener(<span class="hljs-string">'abort'</span>, onCanceled)
}
</code></pre>
<p><code>cancelToken</code> uses the publish-subscribe model to notify axios to cancel the request. Although this part is implemented by axios, it originated from a tc39 abandoned <a target="_blank" href="https://github.com/tc39/proposal-cancelable-promises">proposal cancelable promises</a>.</p>
<p><code>AbortController</code> is an interface that can already be used in browsers. As its name suggests, this is a controller for aborting action. Mdn use Ajax request for an instance, but they use <code>fetch</code> which is more popular now. It can be seen that the practice of axios and fetch is consistent:</p>
<pre><code class="lang-javascript"> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchVideo</span>(<span class="hljs-params"></span>) </span>{
  controller = <span class="hljs-keyword">new</span> AbortController()
  <span class="hljs-keyword">const</span> signal = controller.signal
  fetch(url, { signal })
    .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">response</span>) </span>{
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Download complete'</span>, response)
    })
    .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Download error: '</span> + e.message)
    })
}

abortBtn.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (controller) controller.abort()
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Download aborted'</span>)
})
</code></pre>
<h2 id="heading-other-uses-of-abortcontroller">Other uses of AbortController</h2>
<p>Of course, <code>AbortController</code> not only use to cancel Ajax. We can find two more usage in the <a target="_blank" href="https://dom.spec.whatwg.org/">dom specification document</a> :</p>
<p>A more practical example is to cancel the event listener with <code>AbortController</code>:</p>
<pre><code> <span class="hljs-keyword">dictionary</span> AddEventListenerOptions : EventListenerOptions {
  <span class="hljs-type">boolean</span> passive = <span class="hljs-keyword">false</span>;
  <span class="hljs-type">boolean</span> once = <span class="hljs-keyword">false</span>;
  AbortSignal signal;
};
</code></pre><p>By passing the <code>signal</code> to the <code>AddEventListener</code>, we can run <code>abort()</code> to cancel the event listener. This method is especially useful while we pass anonymous function to <code>AddEventListener</code>.</p>
<p>Another example is for aborting <code>promise</code>s . This is a relatively simple and self-documenting method... But in fact, it is not necessary to <code>AbortController</code> to achieve the goal, as long as you find a way to get the <code>reject</code> function of the <code>promise</code>. I think the point of this example is to learn to use the <code>onabort</code> event:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> controller = <span class="hljs-keyword">new</span> AbortController();
<span class="hljs-keyword">const</span> signal = controller.signal;

startSpinner();

doAmazingness({ ..., signal })
  .then(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> ...)
  .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (err.name == <span class="hljs-string">'AbortError'</span>) <span class="hljs-keyword">return</span>;
    showUserErrorMessage();
  })
  .then(<span class="hljs-function">() =&gt;</span> stopSpinner());

<span class="hljs-comment">// …</span>

controller.abort();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doAmazingness</span>(<span class="hljs-params">{signal}</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    signal.throwIfAborted();

    <span class="hljs-comment">// Begin doing amazingness, and call resolve(result) when done.</span>
    <span class="hljs-comment">// But also, watch for signals:</span>
    signal.addEventListener(<span class="hljs-string">'abort'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// Stop doing amazingness, and:</span>
      reject(signal.reason);
    });
  });
}
</code></pre>
<p>In short, <code>signal</code> is a simple transmitter, and its functionality is to canceling an operation. If you don't want to implement a pubsub object yourself in some case, use this and you're done.</p>
<p>This is the end of the introduction of <code>AbortController</code>. I wonder if everyone has forgotten the title of this post... Finally, I want to discuss whether it is useful to cancel Ajax?</p>
<h2 id="heading-to-cancel-or-not-to-cancel-that-is-the-question">To cancel or not to cancel, that is the question</h2>
<p>In fact, Ajax cancellation is just for the front-end itself. In the view of the back-end programs, they doesn't know the request is aborted. So requests passed to the server still need to be executed. If the back-end program does not have specialized processing, it will still run hard for your 10s cost request.</p>
<p>So, does the "optimization" seen in some articles, the so-called "cancel requests, and only keep the last request" really makes sense?</p>
<p>That's a case-by-case thing. For requests to modify data such as <code>POST</code>, even if the request is slow every time, the server is already processing it. It is meaningless to cancel the previous <code>POST</code> and send it again.</p>
<p>For <code>GET</code>, and only for some extreme operations, ajax cancellation may have a little effect. For example, there is a request to fetch very large table data. The result is not obtained, and then the user uses search to quickly return a small amount of data and render it. Later, the super large table data is actually returned and it will overwrite the searched data. Here is ajax should be cancelled. There is also the cancellation of download and upload, but it is rare case.</p>
<p>Finally, there is a reasonable but in fact useless benefit: reduce request quantity. After all, the number of simultaneous requests for a domain name in the browser is limited. In more cases, setting the <code>timeout</code> option is more practical. Hmm...unless there are five or six super slow requests lined up at the same time...</p>
<p>My personal suggestion is that cancellation is a special treatment for very specific cases. It's good to know this, but there is no need to actually use it.</p>
<p>And, What do you think?</p>
]]></content:encoded></item><item><title><![CDATA[How does Vue reactivity work]]></title><description><![CDATA[In recent years, I have read a lot of articles about the mechanism of Vue2.0. With their help, I pore over the source code of Vue. And now, I think it's time to export something about it by myself. I hope this post can help you to understand Vue more...]]></description><link>https://hn.ssshooter.com/how-does-vue-reactivity-work</link><guid isPermaLink="true">https://hn.ssshooter.com/how-does-vue-reactivity-work</guid><category><![CDATA[Vue.js]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[DJJo]]></dc:creator><pubDate>Sat, 04 Jun 2022 10:08:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1654337167789/t_Djt1yGm.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In recent years, I have read a lot of articles about the mechanism of Vue2.0. With their help, I pore over the source code of Vue. And now, I think it's time to export something about it by myself. I hope this post can help you to understand Vue more deeply from a different perspective.</p>
<p>In the first post, we will learn about the most elaborate design—reactivity.</p>
<p>Before we dive into the core code, we should understand those conceptions ↓</p>
<h2 id="heading-dep">Dep</h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> Dep = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Dep</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">this</span>.id = uid++
  <span class="hljs-built_in">this</span>.subs = []
}
</code></pre>
<p><code>Dep</code> means dependency.  Like writing a node.js program, we will use dependencies on npm. In Vue, what we depend is the data which is reactive. I will soon mention the core function of Vue reactivity—<code>defineReactive</code>.</p>
<p>A reactive data becomes a dependency when it binds with a dep.</p>
<h3 id="heading-subs">subs</h3>
<p>Dep object has a subs property, which is an array. As we guess, it's a list of subscribers. There are three kinds of "watcher"—<code>watch</code>, <code>computed</code>, and render function.</p>
<h2 id="heading-watcher">Watcher</h2>
<p><code>Watcher</code> is the subscriber of <code>Dep</code>(don't mix it with the Observer).</p>
<p>Dep's update can be responded to by Watcher. It's like you subscribe to a YouTube channel(Dep), you(Watcher) will immediately watch the new clip right after you get the update notification.</p>
<h3 id="heading-deps">deps</h3>
<p>The function of <code>deps</code> is similar to that of <code>subs</code> (from <code>Dep</code>). This design provide a many to many relationship between <code>Watcher</code> and <code>Dep</code>. While one of <code>Watcher</code> or <code>Dep</code> is removed, the other one will be updated.</p>
<h3 id="heading-how-to-create-watcher">How to create Watcher</h3>
<p>There are three kinds of "watcher", which have been mentioned before. We can find how they are created in the source code.</p>
<ul>
<li><code>mountComponent</code> 的 <code>vm._watcher = new Watcher(vm, updateComponent, noop);</code></li>
<li><code>initComputed</code> 的 <code>watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions)</code></li>
<li><code>$watcher</code> 的 <code>var watcher = new Watcher(vm, expOrFn, cb, options);</code></li>
</ul>
<h2 id="heading-observer">Observer</h2>
<p>The responsibility of <code>Observer</code> is to "observe" data or array <em>recursively</em>. When you log the Vue instance in the console, you may notice that there is a <code>__ob__</code> property in reactive data, which is the proof of "observed".</p>
<h3 id="heading-walk">walk</h3>
<p><code>Observer.prototype.walk</code> is the core function that <code>Observer</code> uses to process objects. For arrays, <code>Observer.prototype.observeArray</code> is used.</p>
<h2 id="heading-reactivity-processing">Reactivity processing</h2>
<p>Now that we understand those conceptions mentioned above, how can we achieve reactivity with them?</p>
<p>Set our goal first: When reactive data is updated, user can see the newest data (Of course, this process should be automatic.)</p>
<p>That's easy, as we know, reactive data is <code>Dep</code> and the render function (what user can see is generated by this function) is <code>Watcher</code> (and It's the most important <code>Watcher</code>).</p>
<p>But the question is, How <code>Dep</code> know which <code>Watcher</code> is depending it?</p>
<p>The interesting thing comes:</p>
<ul>
<li>Record the current watcher (in <code>Dep.target</code>) before running the callback function of it.</li>
<li>The getter function of the reactive data, which is used by the watcher, must be triggered.</li>
<li>The Current Watcher is recorded by the getter function, and the relationship between Dep and Watcher is constructed.</li>
<li>When we update reactive data, the setter function of it must be triggered.</li>
<li>Base on the relationship constructed before, the related Watcher callback function can be triggered in the setter function.</li>
</ul>
<h2 id="heading-source-code">Source code</h2>
<p>In fact, the process above is implemented by the <code>defineReactive</code> function. This function is invoked in many places. Let's see the most important—<code>observe</code> function.</p>
<p><code>observe</code> function create <code>Observer</code> object, then process data using <code>defineReactive</code> in <code>Observer.prototype.walk</code>.</p>
<p><code>defineReactive</code> is important and concise, so I paste it here.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">defineReactive</span>(<span class="hljs-params">obj, key, val, customSetter, shallow</span>) </span>{
  <span class="hljs-keyword">var</span> dep = <span class="hljs-keyword">new</span> Dep()
  depsArray.push({ dep, obj, key })
  <span class="hljs-keyword">var</span> property = <span class="hljs-built_in">Object</span>.getOwnPropertyDescriptor(obj, key)
  <span class="hljs-keyword">if</span> (property &amp;&amp; property.configurable === <span class="hljs-literal">false</span>) {
    <span class="hljs-keyword">return</span>
  }

  <span class="hljs-comment">// cater for pre-defined getter/setters</span>
  <span class="hljs-keyword">var</span> getter = property &amp;&amp; property.get
  <span class="hljs-keyword">var</span> setter = property &amp;&amp; property.set

  <span class="hljs-keyword">var</span> childOb = !shallow &amp;&amp; observe(val)
  <span class="hljs-built_in">Object</span>.defineProperty(obj, key, {
    <span class="hljs-attr">enumerable</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">configurable</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">get</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reactiveGetter</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">var</span> value = getter ? getter.call(obj) : val
      <span class="hljs-keyword">if</span> (Dep.target) {
        dep.depend()
        <span class="hljs-keyword">if</span> (childOb) {
          childOb.dep.depend()
          <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Array</span>.isArray(value)) {
            dependArray(value)
          }
        }
      }
      <span class="hljs-keyword">return</span> value
    },
    <span class="hljs-attr">set</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reactiveSetter</span>(<span class="hljs-params">newVal</span>) </span>{
      <span class="hljs-keyword">var</span> value = getter ? getter.call(obj) : val
      <span class="hljs-comment">// NaN situation</span>
      <span class="hljs-keyword">if</span> (newVal === value || (newVal !== newVal &amp;&amp; value !== value)) {
        <span class="hljs-keyword">return</span>
      }
      <span class="hljs-keyword">if</span> (<span class="hljs-string">'development'</span> !== <span class="hljs-string">'production'</span> &amp;&amp; customSetter) {
        customSetter()
      }
      <span class="hljs-keyword">if</span> (setter) {
        setter.call(obj, newVal)
      } <span class="hljs-keyword">else</span> {
        val = newVal
      }
      childOb = !shallow &amp;&amp; observe(newVal)
      dep.notify()
    },
  })
}
</code></pre>
<p>Every single property of a reactive object is a "dependency" so the first step is to create a <code>Dep</code> for it by using a closure. (closure will not be needed in Vue3)</p>
<p>Look at the parameters:</p>
<ul>
<li>obj: the object waiting for reactivity processing</li>
<li>key</li>
<li>val: current value, which may be defined a getter and a setter</li>
</ul>
<h3 id="heading-getter">getter</h3>
<p>Previous I mention that the getter function constructs the relationship between <code>Dep</code> and <code>Watcher</code>, and more precisely is achieved by <code>dep.depend()</code>.</p>
<p>Below is some function about the interoperation of <code>Dep</code> and <code>Watcher</code>:</p>
<pre><code class="lang-javascript">Dep.prototype.depend = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">depend</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (Dep.target) {
    Dep.target.addDep(<span class="hljs-built_in">this</span>)
  }
}
Watcher.prototype.addDep = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addDep</span>(<span class="hljs-params">dep</span>) </span>{
  <span class="hljs-keyword">var</span> id = dep.id
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.newDepIds.has(id)) {
    <span class="hljs-built_in">this</span>.newDepIds.add(id)
    <span class="hljs-built_in">this</span>.newDeps.push(dep)
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.depIds.has(id)) {
      dep.addSub(<span class="hljs-built_in">this</span>)
    }
  }
}
Dep.prototype.addSub = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addSub</span>(<span class="hljs-params">sub</span>) </span>{
  <span class="hljs-built_in">this</span>.subs.push(sub)
}
</code></pre>
<p>It seems intricate between <code>Dep</code> and <code>Watcher</code>, but what those functions actually do is to create the many to many relationship.</p>
<p>You can find all subscribers of a <code>Dep</code> in its <code>subs</code> property, and all <code>Dep</code>s that a <code>Watcher</code> is watching in its <code>deps</code> property.</p>
<p>There is a question hidden here—where is <code>Dep.target</code> set? Don't hurry; I'll tell you later.</p>
<h3 id="heading-setter">setter</h3>
<p>The Key function in the setter function is <code>dep.notify()</code>.</p>
<pre><code class="lang-javascript">Dep.prototype.notify = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">notify</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// stabilize the subscriber list first</span>
  <span class="hljs-keyword">var</span> subs = <span class="hljs-built_in">this</span>.subs.slice()
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, l = subs.length; i &lt; l; i++) {
    subs[i].update()
  }
}
</code></pre>
<p>It's not hard to understand. <code>Dep</code> notify its subscribers (in <code>subs</code>) to update. <code>subs[i].update()</code> invoke <code>Watcher.prototype.update</code>.Let's see what it does:</p>
<pre><code class="lang-javascript">Watcher.prototype.update = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">update</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.lazy) {
    <span class="hljs-built_in">this</span>.dirty = <span class="hljs-literal">true</span>
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.sync) {
    <span class="hljs-built_in">this</span>.run()
  } <span class="hljs-keyword">else</span> {
    queueWatcher(<span class="hljs-built_in">this</span>)
  }
}
</code></pre>
<p>There are two points I think we can dive into:</p>
<ul>
<li>If it updates asynchronously, <code>queueWatcher</code> will run. But it eventually <code>run</code>.</li>
<li>The sequence of running <code>watch</code>, <code>computed</code>, and render function is worth noticing.</li>
<li>The <code>lazy</code> flag is used for <code>computed</code> values.</li>
</ul>
<p>I may talk about them in the next few posts.</p>
<pre><code class="lang-javascript">Watcher.prototype.run = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.active) {
    <span class="hljs-keyword">var</span> value = <span class="hljs-built_in">this</span>.get()
    <span class="hljs-keyword">if</span> (
      value !== <span class="hljs-built_in">this</span>.value ||
      <span class="hljs-comment">// Deep watchers and watchers on Object/Arrays should fire even</span>
      <span class="hljs-comment">// when the value is the same, because the value may</span>
      <span class="hljs-comment">// have mutated.</span>
      isObject(value) ||
      <span class="hljs-built_in">this</span>.deep
    ) {
      <span class="hljs-comment">// set new value</span>
      <span class="hljs-keyword">var</span> oldValue = <span class="hljs-built_in">this</span>.value
      <span class="hljs-built_in">this</span>.value = value
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.user) {
        <span class="hljs-keyword">try</span> {
          <span class="hljs-built_in">this</span>.cb.call(<span class="hljs-built_in">this</span>.vm, value, oldValue)
        } <span class="hljs-keyword">catch</span> (e) {
          handleError(
            e,
            <span class="hljs-built_in">this</span>.vm,
            <span class="hljs-string">'callback for watcher "'</span> + <span class="hljs-built_in">this</span>.expression + <span class="hljs-string">'"'</span>
          )
        }
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">this</span>.cb.call(<span class="hljs-built_in">this</span>.vm, value, oldValue)
      }
    }
  }
}
</code></pre>
<p>The important thing of this code clip is that <code>Dep.target</code> is set here (run -&gt; get -&gt; pushTarget).</p>
<p>Because of the existence of <code>Dep.target</code>, <code>Dep.prototype.depend</code> invoked by Watcher <code>cb</code> makes sense. That's the answer to the unsolved question.</p>
<h2 id="heading-wrap-up">Wrap up</h2>
<ul>
<li>An object bind with a <code>Dep</code>, and it become a dependancy.</li>
<li><code>watch</code>, <code>computed</code>, and render functions are <code>Watcher</code>s, and they can be subscribers of dependancy.</li>
<li><code>Observer</code> is an entry to process reactive data recursively.</li>
<li><code>Watcher</code> will set <code>Dep.target</code> before running callback function.</li>
<li>The getter function of reactive data perceive its "Caller" from <code>Dep.target</code> and construct relationship with <code>Watcher</code></li>
<li>The setter function of reactive data traverse its <code>subs</code> and notify them to run their update function.</li>
<li>While the <code>Watcher</code> runs render function (<code>updateComponent</code> -&gt; <code>_update</code>), user can see the newest data on the web page.</li>
</ul>
<p>Though understanding the fundamental algorithm is not so hard, there are still many details this post doesn't mention yet. For example, the update queue and the component update function itself are worth studying.</p>
<p>I hope you enjoy this post!</p>
<p><a target="_blank" href="https://ssshooter.com/2021-07-15-how-does-vue-work-1/">Read this post in Chinese</a></p>
<h2 id="heading-reference">Reference</h2>
<ul>
<li><a target="_blank" href="https://github1s.com/vuejs/vue/blob/HEAD/dist/vue.js">Vue.js source code</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Hi, there]]></title><description><![CDATA[Usubeni Fantasy hashnode branch is open now, welcome!]]></description><link>https://hn.ssshooter.com/hi-there</link><guid isPermaLink="true">https://hn.ssshooter.com/hi-there</guid><dc:creator><![CDATA[DJJo]]></dc:creator><pubDate>Sat, 28 May 2022 14:11:55 GMT</pubDate><content:encoded><![CDATA[<p>Usubeni Fantasy hashnode branch is open now, welcome! </p>
]]></content:encoded></item></channel></rss>