Skip to content

Commit

Permalink
Call one timers before finishing navigation
Browse files Browse the repository at this point in the history
If one timers are called after navigation, then it is never called for an async route
  • Loading branch information
pshrmn committed Sep 13, 2018
1 parent fecac86 commit 381febd
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 20 deletions.
24 changes: 12 additions & 12 deletions packages/router/.size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"dist/curi-router.es.js": {
"bundled": 17615,
"minified": 6201,
"gzipped": 2572,
"bundled": 18977,
"minified": 6574,
"gzipped": 2652,
"treeshaked": {
"rollup": {
"code": 23,
Expand All @@ -14,18 +14,18 @@
}
},
"dist/curi-router.js": {
"bundled": 17848,
"minified": 6383,
"gzipped": 2646
"bundled": 19210,
"minified": 6756,
"gzipped": 2724
},
"dist/curi-router.umd.js": {
"bundled": 30803,
"minified": 8933,
"gzipped": 3763
"bundled": 32305,
"minified": 9306,
"gzipped": 3839
},
"dist/curi-router.min.js": {
"bundled": 30660,
"minified": 8847,
"gzipped": 3717
"bundled": 32162,
"minified": 9220,
"gzipped": 3793
}
}
16 changes: 8 additions & 8 deletions packages/router/src/curi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export default function createRouter(

activeNavigation = undefined;

callOneTimersAndSideEffects({ response, navigation, router });
callSideEffects({ response, navigation, router });
};
}

Expand All @@ -183,14 +183,14 @@ export default function createRouter(
finishCallback = undefined;
}

function callObservers(emitted: Emitted) {
observers.forEach(fn => {
function callObserversAndOneTimers(emitted: Emitted) {
[...observers, ...oneTimers.splice(0)].forEach(fn => {
fn(emitted);
});
}

function callOneTimersAndSideEffects(emitted: Emitted) {
[...oneTimers.splice(0), ...sideEffects].forEach(fn => {
function callSideEffects(emitted: Emitted) {
sideEffects.forEach(fn => {
fn(emitted);
});
}
Expand All @@ -206,8 +206,8 @@ export default function createRouter(
mostRecent.response = response;
mostRecent.navigation = navigation;

callObservers({ response, navigation, router });
callOneTimersAndSideEffects({ response, navigation, router });
callObserversAndOneTimers({ response, navigation, router });
callSideEffects({ response, navigation, router });
}

if (response.redirectTo !== undefined) {
Expand All @@ -221,7 +221,7 @@ export default function createRouter(
mostRecent.response = response;
mostRecent.navigation = navigation;

callObservers({ response, navigation, router });
callObserversAndOneTimers({ response, navigation, router });
}

if (response.redirectTo !== undefined) {
Expand Down
80 changes: 80 additions & 0 deletions packages/router/tests/curi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,44 @@ describe("curi", () => {
router.observe(check);
});

describe("suspend", () => {
it("calls function before navigation is finished", done => {
const routes = [
{ name: "Home", path: "" },
{ name: "About", path: "about" },
{
name: "Contact",
path: "contact",
children: [
{
name: "How",
path: ":method",
resolve: {
test: () => Promise.resolve()
}
}
]
}
];
const history = InMemory({ locations: ["/"] });
const router = curi(history, routes, {
suspend: true
});
// Register an observer function, but don't call it immediately
// so that we can compare its received location to the history's
// current location.
router.observe(
({ response }) => {
expect(response.location.pathname).toBe("/contact/phone");
expect(history.location.pathname).toBe("/");
done();
},
{ initial: false }
);
history.navigate("/contact/phone");
});
});

it("does not emit responses for cancelled navigation", done => {
const routes = [
{ name: "Home", path: "" },
Expand Down Expand Up @@ -1037,6 +1075,48 @@ describe("curi", () => {
router.once(check);
});

describe("suspend", () => {
it("calls function before navigation is finished", done => {
const routes = [
{ name: "Home", path: "" },
{ name: "About", path: "about" },
{
name: "Contact",
path: "contact",
children: [
{
name: "How",
path: ":method",
resolve: {
test: () => Promise.resolve()
}
}
]
}
];
const history = InMemory({ locations: ["/"] });
const router = curi(history, routes, {
suspend: true
});
// Register a one timer function, but don't call it immediately
// so that we can compare its received location to the history's
// current location.
// While router.once() is typically used with the initial location,
// the easiest way to verify that a one time function is called before
// finishing navigation is to verify that its location is the new one,
// while the history's is the old one.
router.once(
({ response }) => {
expect(response.location.pathname).toBe("/contact/phone");
expect(history.location.pathname).toBe("/");
done();
},
{ initial: false }
);
history.navigate("/contact/phone");
});
});

it("does not emit responses for cancelled navigation", done => {
const routes = [
{ name: "Home", path: "" },
Expand Down

0 comments on commit 381febd

Please sign in to comment.