From fb0fca068e211a8b3e2ef26bb86255a3af05d8b3 Mon Sep 17 00:00:00 2001 From: Kazuyoshi Kato Date: Thu, 5 Dec 2019 06:38:01 -0800 Subject: [PATCH] Make / work under FastBoot This commit adds a transparent cache called "fetcher" to prevent making 2 XHRs (both from the frontend to the backend). --- app/controllers/index.js | 28 +--------------------------- app/routes/index.js | 21 ++++++++++++++++++--- app/services/fetcher.js | 31 +++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 30 deletions(-) create mode 100644 app/services/fetcher.js diff --git a/app/controllers/index.js b/app/controllers/index.js index 6d057737714..6b5263cde0c 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -1,31 +1,5 @@ import Controller from '@ember/controller'; -import { computed } from '@ember/object'; -import { readOnly } from '@ember/object/computed'; - -import ajax from 'ember-fetch/ajax'; -import { task } from 'ember-concurrency'; export default Controller.extend({ - model: readOnly('dataTask.lastSuccessful.value'), - - hasData: computed('dataTask.{lastSuccessful,isRunning}', function() { - return this.get('dataTask.lastSuccessful') || !this.get('dataTask.isRunning'); - }), - - dataTask: task(function*() { - let data = yield ajax('/api/v1/summary'); - - addCrates(this.store, data.new_crates); - addCrates(this.store, data.most_downloaded); - addCrates(this.store, data.just_updated); - addCrates(this.store, data.most_recently_downloaded); - - return data; - }).drop(), + hasData: true, }); - -function addCrates(store, crates) { - for (let i = 0; i < crates.length; i++) { - crates[i] = store.push(store.normalize('crate', crates[i])); - } -} diff --git a/app/routes/index.js b/app/routes/index.js index b4a8f83619a..3b0b52f8838 100644 --- a/app/routes/index.js +++ b/app/routes/index.js @@ -1,6 +1,9 @@ import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; export default Route.extend({ + fetcher: service(), + headTags() { return [ { @@ -13,8 +16,20 @@ export default Route.extend({ ]; }, - setupController(controller) { - this.controllerFor('application').set('searchQuery', null); - controller.dataTask.perform(); + model() { + return this.fetcher.ajax('/api/v1/summary'); + }, + + afterModel(model, transition) { + addCrates(this.store, model.new_crates); + addCrates(this.store, model.most_downloaded); + addCrates(this.store, model.just_updated); + addCrates(this.store, model.most_recently_downloaded); }, }); + +function addCrates(store, crates) { + for (let i = 0; i < crates.length; i++) { + crates[i] = store.push(store.normalize('crate', crates[i])); + } +} diff --git a/app/services/fetcher.js b/app/services/fetcher.js new file mode 100644 index 00000000000..dcf1dc22997 --- /dev/null +++ b/app/services/fetcher.js @@ -0,0 +1,31 @@ +import Service, { inject as service } from '@ember/service'; +import ajax from 'ember-fetch/ajax'; + +export default Service.extend({ + fastboot: service(), + + ajax(url) { + let fastboot = this.fastboot; + let shoebox = this.fastboot.shoebox; + let cache = shoebox.retrieve('ajax-cache'); + if (!cache) { + cache = {}; + } + + if (cache[url]) { + return cache[url]; + } + + return ajax(url).then(function(resp) { + if (shoebox && fastboot.isFastBoot) { + cache[url] = deepCopy(resp); + shoebox.put('ajax-cache', cache); + } + return resp; + }); + }, +}); + +function deepCopy(obj) { + return JSON.parse(JSON.stringify(obj)); +}