Skip to content

Commit f24002c

Browse files
committed
Implement a function to defer rendering via promise chaining (#169)
Service side of ember-fastboot/fastboot#41
1 parent b1dbd9f commit f24002c

6 files changed

Lines changed: 96 additions & 1 deletion

File tree

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ check if you are running within FastBoot by checking
110110
`fastboot.request` which exposes details about the current request being
111111
handled by FastBoot
112112

113+
### Delaying the server response
114+
115+
By default, FastBoot waits for the `beforeModel`, `model`, and
116+
`afterModel` hooks to resolve before sending the response back to the
117+
client. If you have asynchrony that runs outside of those contexts, your
118+
response may not reflect the state that you want. To solve this, the
119+
`fastboot` service has `deferRendering` function that accepts a promise.
120+
It will chain all promises passed to it, and the FastBoot server will
121+
wait until all of these promises resolve before sending the response to
122+
the client. These promises must be chained before the rendering is
123+
complete after the model hooks. For example, if a component that is
124+
rendered into the page makes an async call for data, registering a
125+
promise to be resolved in its `init` hook would allow the component to
126+
defer the rendering of the page.
127+
113128
### Cookies
114129

115130
You can access cookies for the current request via `fastboot.request`

app/services/fastboot.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,10 @@ export default Ember.Service.extend({
4848

4949
isFastBoot: computed(function() {
5050
return typeof FastBoot !== 'undefined';
51-
})
51+
}),
52+
53+
deferRendering(promise) {
54+
Ember.assert('deferRendering requires a promise or thennable object', promise.then);
55+
this._fastbootInfo.deferRendering(promise);
56+
}
5257
});
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var chai = require('chai');
2+
var expect = chai.expect;
3+
var RSVP = require('rsvp');
4+
var AddonTestApp = require('ember-cli-addon-tests').AddonTestApp;
5+
var request = require('request');
6+
var get = RSVP.denodeify(request);
7+
8+
describe('async content via deferred content', function() {
9+
this.timeout(300000);
10+
11+
var app;
12+
13+
before(function() {
14+
15+
app = new AddonTestApp();
16+
17+
return app.create('async-content')
18+
.then(function() {
19+
return app.startServer({
20+
command: 'fastboot',
21+
additionalArguments: ['--serve-assets']
22+
});
23+
});
24+
});
25+
26+
after(function() {
27+
return app.stopServer();
28+
});
29+
30+
it('waits for async content when using `fastboot.deferRendering`', function() {
31+
return get({
32+
url: 'http://localhost:49741/'
33+
})
34+
.then(function(response) {
35+
expect(response.body).to.contain('Async content: foo');
36+
});
37+
});
38+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import Ember from 'ember';
2+
3+
export default Ember.Component.extend({
4+
fastboot: Ember.inject.service(),
5+
6+
init() {
7+
this._super(...arguments);
8+
9+
let deferred = Ember.RSVP.defer();
10+
11+
let runLater = Ember.run.later(() => {
12+
this.set('setLater', 'foo');
13+
deferred.resolve()
14+
this.set('runLater', null);
15+
this.set('deferred', null);
16+
}, 100);
17+
18+
this.runLater = runLater;
19+
this.deferred = deferred;
20+
21+
this.get('fastboot').deferRendering(deferred.promise);
22+
},
23+
24+
destroy() {
25+
let runLater = this.get('runLater');
26+
let deferred = this.get('deferred');
27+
28+
if (runLater) {
29+
Ember.run.cancel(runLater);
30+
deferred.reject('cancelled');
31+
}
32+
33+
this._super(...arguments);
34+
}
35+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{async-content}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Async content: {{setLater}}

0 commit comments

Comments
 (0)