-
Notifications
You must be signed in to change notification settings - Fork 202
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use requestAnimationFrame to fire each queue item.
- Loading branch information
1 parent
72d834b
commit b2c6e74
Showing
6 changed files
with
193 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import * as beforePaint from "../../src/helpers/beforePaint"; | ||
import fireItem from "../../src/helpers/fireItem"; | ||
|
||
describe("all items have delays", () => { | ||
it("does not group any items for execution.", async () => { | ||
const beforePaintSpy = jest | ||
.spyOn(beforePaint, "default") | ||
.mockImplementation((cb) => cb()); | ||
const wait = jest.fn((cb) => cb()); | ||
const [mock1, mock2] = makeMocks(); | ||
const queueItems = [ | ||
[ | ||
Symbol(), | ||
{ | ||
func: mock1, | ||
delay: 1, | ||
}, | ||
], | ||
[ | ||
Symbol(), | ||
{ | ||
func: mock2, | ||
delay: 1, | ||
}, | ||
], | ||
]; | ||
|
||
const index = 0; | ||
const resultIndex = await fireItem(index, queueItems, wait); | ||
|
||
expect(beforePaintSpy).toHaveBeenCalledTimes(1); | ||
expect(mock1).toHaveBeenCalledTimes(1); | ||
expect(mock2).not.toHaveBeenCalled(); | ||
|
||
// Index was not modified. | ||
expect(resultIndex).toBe(index); | ||
expect(wait).toHaveBeenCalledTimes(1); | ||
}); | ||
}); | ||
|
||
describe("some items have no delay", () => { | ||
it("groups items for execution.", async () => { | ||
const [mock1, mock2, mock3, mock4] = makeMocks(); | ||
const wait = jest.fn(); | ||
const queueItems = [ | ||
[ | ||
Symbol(), | ||
{ | ||
func: mock1, | ||
delay: 0, | ||
}, | ||
], | ||
[ | ||
Symbol(), | ||
{ | ||
func: mock2, | ||
delay: 0, | ||
}, | ||
], | ||
[ | ||
Symbol(), | ||
{ | ||
func: mock3, | ||
delay: 0, | ||
}, | ||
], | ||
[ | ||
Symbol(), | ||
{ | ||
func: mock4, | ||
delay: 1, | ||
}, | ||
], | ||
]; | ||
|
||
const index = 0; | ||
const resultIndex = await fireItem(index, queueItems, wait); | ||
|
||
[mock1, mock2, mock3].forEach((m) => { | ||
expect(m).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
expect(mock4).not.toHaveBeenCalled(); | ||
|
||
// Index was advanced. | ||
expect(resultIndex).toBe(2); | ||
expect(wait).not.toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
let beforePaint = (cb): Promise<any> => { | ||
return new Promise((resolve) => { | ||
requestAnimationFrame(async () => { | ||
resolve(await cb()); | ||
}) | ||
}); | ||
} | ||
|
||
export default beforePaint; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,44 @@ | ||
import { QueueItem } from "../types"; | ||
|
||
let fireItem = async (queueItem: QueueItem, wait) => { | ||
// Only break up the event loop if needed. | ||
let execute = async () => queueItem.func?.call(this); | ||
|
||
if (queueItem.delay) { | ||
await wait(async () => { | ||
await execute(); | ||
}, queueItem.delay); | ||
} else { | ||
await execute(); | ||
import { QueueItem, QueueMapPair } from "../types"; | ||
import beforePaint from "./beforePaint"; | ||
|
||
let execute = (queueItem: QueueItem) => queueItem.func?.call(this); | ||
|
||
let fireItem = async ( | ||
index: number, | ||
queueItems: QueueMapPair[], | ||
wait | ||
): Promise<number> => { | ||
let queueItem = queueItems[index][1]; | ||
let instantQueue = []; | ||
let tempIndex = index; | ||
let futureItem = queueItem; | ||
let shouldBeGrouped = () => futureItem && !futureItem.delay; | ||
|
||
// Crawl through the queue and group together all items that | ||
// do not have have a delay and can be executed instantly. | ||
while (shouldBeGrouped()) { | ||
instantQueue.push(futureItem); | ||
|
||
shouldBeGrouped() && tempIndex++; | ||
futureItem = queueItems[tempIndex] ? queueItems[tempIndex][1] : null; | ||
} | ||
} | ||
|
||
if (instantQueue.length) { | ||
// All are executed together before the browser has a chance to repaint. | ||
await beforePaint(async () => { | ||
for (let q of instantQueue) { | ||
await execute(q); | ||
} | ||
}); | ||
|
||
// Important! Because we moved into the future, the index | ||
// needs to be modified and returned for accurate remaining execution. | ||
return tempIndex - 1; | ||
} | ||
|
||
await wait(() => beforePaint(() => execute(queueItem)), queueItem.delay); | ||
|
||
return index; | ||
}; | ||
|
||
export default fireItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters