前端学堂
学有所用

React Batch update机制?

面试笔试分类: JavaScriptReact Batch update机制?
0
前端学堂 管理员 asked 2 years ago

文章目录[隐藏]

Batch Update 即「批量更新」。在 MV* 框架中,Batch Update 可以理解为将一段时间内对 model 的修改批量更新到 view 的机制。以 React 为例,我们在 componentDidMount 生命周期连续调用 setState :

componentDidMount () {
  this.setState({ foo: 1 })
  this.setState({ foo: 2 })
  this.setState({ foo: 3 })
}

在不引入 Batch Update 的情况下,上面的操作会导致三次组件渲染,而实际运行上面的代码可以发现组件只渲染了一次。componentDidMount 中三次对 model 的操作被 Batch Update 优化为一次 view 的更新,不必要的 Virtual DOM 计算被省略,从而提高了框架的效率。

Batch Update 的实现

我们很容易想到使用一个 queue 来保存 update,并在合适的时候对这个 queue 进行 flush 操作。但在前端框架中实现 Batch Update 的关键在于两个问题:

  1. 何时开始一个 queue
  2. 何时 flush 这个 queue

主流的前端框架都有自己的 Batch Update 实现。以 React 和 Vue 为例,这两个框架用完全不同思路实现了 Batch Update。

首先是 React:React 中的 Batch Update 是通过「Transaction」实现的。在 React 源码关于 Transaction 的部分,用一大段文字及一幅字符画解释了 Transaction 的作用:

*                       wrappers (injected at creation time)
*                                      +        +
*                                      |        |
*                    +-----------------|--------|--------------+
*                    |                 v        |              |
*                    |      +---------------+   |              |
*                    |   +--|    wrapper1   |---|----+         |
*                    |   |  +---------------+   v    |         |
*                    |   |          +-------------+  |         |
*                    |   |     +----|   wrapper2  |--------+   |
*                    |   |     |    +-------------+  |     |   |
*                    |   |     |                     |     |   |
*                    |   v     v                     v     v   | wrapper
*                    | +---+ +---+   +---------+   +---+ +---+ | invariants
* perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained
* +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
*                    | |   | |   |   |         |   |   | |   | |
*                    | |   | |   |   |         |   |   | |   | |
*                    | |   | |   |   |         |   |   | |   | |
*                    | +---+ +---+   +---------+   +---+ +---+ |
*                    |  initialize                    close    |
*                    +-----------------------------------------+

Transaction 对一个函数进行包装,让 React 有机会在一个函数运行前后执行特定逻辑,从而完成整个 Batch Update 流程的控制。

简单来说,在 Transaction 的 initialize 阶段,一个 update queue 被创建。在 Transaction 中调用 setState 方法时,状态并不会立即应用,而是被推入到 update queue 中。函数执行结束进入 Transaction 的 close 阶段,update queue 会被 flush,这时新的状态会被应用到组件上并开始后续 Virtual DOM 更新等工作。

与 React 相比 Vue 实现 Batch Update 的方法就要简单很多:直接借助 JavaScript 的 Event Loop。Vue 中 Batch Update 的核心代码只有大约 20 行:

// https://github.com/vuejs/vue/blob/dev/src/core/observer/scheduler.js#L122-L148
/**
 * Push a watcher into the watcher queue.
 * Jobs with duplicate IDs will be skipped unless it's
 * pushed when the queue is being flushed.
 */
export function queueWatcher (watcher: Watcher) {
  const id = watcher.id
  if (has[id] == null) {
    has[id] = true
    if (!flushing) {
      queue.push(watcher)
    } else {
      // if already flushing, splice the watcher based on its id
      // if already past its id, it will be run next immediately.
      let i = queue.length - 1
      while (i > index && queue[i].id > watcher.id) {
        i--
      }
      queue.splice(i + 1, 0, watcher)
    }
    // queue the flush
    if (!waiting) {
      waiting = true
      nextTick(flushSchedulerQueue)
    }
  }
}

当 model 被修改时,对应的 watcher 会被推入 update queue,与此同时还会在异步队列中添加一个 task 用来 flush 当前 update queue。这样一来,当前 task 中的其他 watcher 会被推入同一个 update queue 中。当前 task 执行结束后,异步队列中的下一个 task 会开始执行,update queue 会被 flush,并进行后续的更新操作。

为了让 flush 动作能在当前 Task 结束后尽可能早的开始,Vue 会优先尝试将任务 micro-task 队列,具体来说,在浏览器环境中 Vue 会优先尝试使用 MutationObserver API 或 Promise,如果两者都不可用,则 fallback 到 setTimeout。

对比两个框架可以发现 React 基于 Transition 实现的 Batch Query 是一个不依赖语言特性的通用模式,因此有更稳定可控的表现,但缺点是无法完全覆盖所有情况,例如对于如下代码:

componentDidMount () {
  setTimeout(_ => {
    this.setState({ foo: 1 })
    this.setState({ foo: 2 })
    this.setState({ foo: 3 })
  }, 0)
}

由于 setTimeout 的回调函数「不受 React 控制」,其中的 setState 就无法得到优化,最终会导致 render 函数执行三次。

而 Vue 的实现则对语言特性乃至运行环境有很强的依赖,但可以更好的覆盖各种情况:只要是在同一个 task 中的修改都可以进行 Batch Update 优化。

1 Answers
0
inpussifs answered 1 month ago

Rogaine [url=https://viacialisns.com/]cialis canada[/url] Levitra Moins Cher Pharmacie Cialis Wirkung Von Viagra Bei Gesunden

Staci replied 2 weeks ago

What's Happening i am new to this, I stumbled upon this I've discovered It absolutely useful and it has helped
me out loads. I hope to give a contribution & aid other
users like its aided me. Good job.

Here is my homepage: https://tinyurl.com/rsacwgxy g

Taren replied 2 weeks ago

I blog quite often and I genuinely appreciate your information. This article has really peaked my interest.
I'm going to book mark your site and keep checking for new details about
once per week. I subscribed to your RSS feed as well.

Have a look at my web page ... cbd oil (https://www.appuntipertutti.it/forums/users/halinat63015404/)

Alina replied 2 weeks ago

Great info. Lucky me I recently found your site by accident (stumbleupon).
I've book-marked it for later!

Look at my web blog ... cbd oil; http://www.gsjh.tyc.edu.tw/~forever/userinfo.php?uid=510782,

Merle replied 2 weeks ago

I'm really impressed with your writing skills and also with the layout on your blog.
Is this a paid theme or did you modify it yourself?
Anyway keep up the nice quality writing, it is rare
to see a nice blog like this one today.

Feel free to surf to my web-site cbd oil
- http://tinyurl.com
-

Augustus replied 2 weeks ago

Inspiring quest there. What happened after?
Good luck!

my web page :: cbd oil; http://www.pasoconya.jp,

Douglas replied 2 weeks ago

Hi there colleagues, its wonderful piece of writing on the topic of teachingand
entirely defined, keep it up all the time.

Here is my webpage - cbd oil that works 2020

Nichole replied 2 weeks ago

Hey there! I just wanted to ask if you ever have any
issues with hackers? My last blog (wordpress) was hacked and I ended up losing
a few months of hard work due to no back up. Do you have any solutions to protect against hackers?

my web site - cbd oil that works 2020

Muhammad replied 2 weeks ago

If some one desires to be updated with most recent technologies then he must
be pay a visit this site and be up to date every day.

My page: cbd oil that works 2020

Zachery replied 2 weeks ago

I just could not go away your site prior to suggesting cbd oil that works 2020 I extremely enjoyed the usual info a person supply on your guests?
Is going to be again often in order to check up on new posts

Lily replied 2 weeks ago

Awesome blog you have here but I was curious about if you knew of any discussion boards that cover
the same topics discussed here? I'd really like to be a part of
online community where I can get comments from other experienced individuals cbd oil that works 2020 share the same interest.

If you have any recommendations, please let me know. Thanks a lot!

Your Answer

 

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏