Skip to content

Commit 6873920

Browse files
authored
Merge pull request #362 from rwjblue/use-promises-first
Use Promise microtask queue as first option.
2 parents 2bee3b4 + ec94f91 commit 6873920

File tree

4 files changed

+54
-12
lines changed

4 files changed

+54
-12
lines changed

lib/backburner/platform.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,41 @@ export interface IPlatform {
99
const SET_TIMEOUT = setTimeout;
1010
const NOOP = () => {};
1111

12-
export function buildPlatform(flush: () => void): IPlatform {
13-
let next;
14-
let clearNext = NOOP;
12+
export function buildNext(flush: () => void): () => void {
13+
// Using "promises first" here to:
14+
//
15+
// 1) Ensure more consistent experience on browsers that
16+
// have differently queued microtasks (separate queues for
17+
// MutationObserver vs Promises).
18+
// 2) Ensure better debugging experiences (it shows up in Chrome
19+
// call stack as "Promise.then (async)") which is more consistent
20+
// with user expectations
21+
//
22+
// When Promise is unavailable use MutationObserver (mostly so that we
23+
// still get microtasks on IE11), and when neither MutationObserver and
24+
// Promise are present use a plain old setTimeout.
25+
if (typeof Promise === 'function') {
26+
const autorunPromise = Promise.resolve();
1527

16-
if (typeof MutationObserver === 'function') {
28+
return () => autorunPromise.then(flush);
29+
} else if (typeof MutationObserver === 'function') {
1730
let iterations = 0;
1831
let observer = new MutationObserver(flush);
1932
let node = document.createTextNode('');
2033
observer.observe(node, { characterData: true });
2134

22-
next = () => {
35+
return () => {
2336
iterations = ++iterations % 2;
2437
node.data = '' + iterations;
2538
return iterations;
2639
};
27-
28-
} else if (typeof Promise === 'function') {
29-
const autorunPromise = Promise.resolve();
30-
next = () => autorunPromise.then(flush);
31-
3240
} else {
33-
next = () => SET_TIMEOUT(flush, 0);
41+
return () => SET_TIMEOUT(flush, 0);
3442
}
43+
}
44+
45+
export function buildPlatform(flush: () => void): IPlatform {
46+
let clearNext = NOOP;
3547

3648
return {
3749
setTimeout(fn, ms) {
@@ -46,7 +58,7 @@ export function buildPlatform(flush: () => void): IPlatform {
4658
return Date.now();
4759
},
4860

49-
next,
61+
next: buildNext(flush),
5062
clearNext,
5163
};
5264
}

lib/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export {
44
} from './backburner/platform';
55

66
import {
7+
buildNext,
78
buildPlatform,
89
IPlatform,
910
} from './backburner/platform';
@@ -153,6 +154,8 @@ export interface IBackburnerOptions {
153154

154155
export default class Backburner {
155156
public static Queue = Queue;
157+
public static buildPlatform = buildPlatform;
158+
public static buildNext = buildNext;
156159

157160
public DEBUG = false;
158161

tests/build-next-test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import Backburner from 'backburner';
2+
3+
QUnit.module('tests/build-next', function() {
4+
5+
QUnit.test('can build custom flushing next', function(assert) {
6+
let done = assert.async();
7+
let next = Backburner.buildNext(() => assert.step('custom next'));
8+
9+
assert.step('start');
10+
Promise.resolve().then(() => assert.step('first promise resolved'));
11+
next();
12+
Promise.resolve().then(() => assert.step('second promise resolved'));
13+
assert.step('end');
14+
15+
setTimeout(() => {
16+
assert.verifySteps([
17+
'start',
18+
'end',
19+
'first promise resolved',
20+
'custom next',
21+
'second promise resolved',
22+
]);
23+
done();
24+
}, 10);
25+
});
26+
});

tests/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import './autorun-test';
22
import './bb-has-timers-test';
3+
import './build-next-test';
34
import './cancel-test';
45
import './configurable-timeout-test';
56
import './debounce-test';

0 commit comments

Comments
 (0)