perf: use requestPostAnimationFrame to reduce layout thrashing (#1376)

This commit is contained in:
Nolan Lawson 2019-08-07 09:11:34 -07:00 committed by GitHub
parent 98e02cf650
commit 87bab8662c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 9 deletions

View file

@ -69,6 +69,7 @@
import { observe } from 'svelte-extras'
import { get } from '../../_utils/lodash-lite'
import { on } from '../../_utils/eventBus'
import { requestPostAnimationFrame } from '../../_utils/requestPostAnimationFrame'
export default {
oncreate () {
@ -117,7 +118,7 @@
},
setupAutosize () {
const textarea = this.refs.textarea
requestAnimationFrame(() => {
requestPostAnimationFrame(() => {
mark('autosize()')
autosize(textarea)
stop('autosize()')

View file

@ -28,12 +28,13 @@
import { virtualListStore } from './virtualListStore'
import { registerResizeListener, unregisterResizeListener } from '../../_utils/resize'
import { mark, stop } from '../../_utils/marks'
import { requestPostAnimationFrame } from '../../_utils/requestPostAnimationFrame'
export default {
oncreate () {
const { key } = this.get()
const node = this.refs.node
requestAnimationFrame(() => {
requestPostAnimationFrame(() => {
if (!node || !key) {
return
}

View file

@ -4,6 +4,7 @@
import { Store } from 'svelte/store.js'
import QuickLRU from 'quick-lru'
import { mark, stop } from './marks'
import { requestPostAnimationFrame } from './requestPostAnimationFrame'
export class RealmStore extends Store {
constructor (init, maxSize) {
@ -47,7 +48,7 @@ export class RealmStore extends Store {
}
batch[subKey] = value
requestAnimationFrame(() => {
requestPostAnimationFrame(() => {
const batch = this._batches[currentRealm] && this._batches[currentRealm][key]
if (!batch) {
return

View file

@ -1,9 +1,33 @@
// modeled after https://github.com/andrewiggins/afterframe
// see also https://github.com/WICG/requestPostAnimationFrame
export const requestPostAnimationFrame = cb => {
requestAnimationFrame(() => {
const channel = new MessageChannel()
channel.port1.onmessage = cb
channel.port2.postMessage(undefined)
})
const channel = process.browser && new MessageChannel()
const callbacks = []
if (process.browser) {
channel.port1.onmessage = onMessage
}
function runCallback (callback) {
try {
callback()
} catch (e) {
console.error(e)
}
}
function onMessage () {
for (const callback of callbacks) {
runCallback(callback)
}
callbacks.length = 0
}
function postMessage () {
channel.port2.postMessage(undefined)
}
export const requestPostAnimationFrame = callback => {
if (callbacks.push(callback) === 1) {
requestAnimationFrame(postMessage)
}
}