Skip to content

Commit 998f73c

Browse files
committed
use promise
1 parent 4e26d98 commit 998f73c

File tree

6 files changed

+72
-85
lines changed

6 files changed

+72
-85
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"webpack-dev-server": "^1.12.0"
3131
},
3232
"dependencies": {
33+
"es6-promise": "^3.0.2",
3334
"firebase": "^2.3.1",
3435
"vue": "^1.0.0",
3536
"vue-router": "^0.7.4"

src/components/comment.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default {
3030
},
3131
created () {
3232
if (this.comment.kids) {
33-
store.fetchItems(this.comment.kids, (comments) => {
33+
store.fetchItems(this.comment.kids).then(comments => {
3434
this.childComments = comments
3535
})
3636
}

src/store/index.js

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import Firebase from 'firebase'
22
import { EventEmitter } from 'events'
3+
import { Promise } from 'es6-promise'
34

45
const api = new Firebase('https://hacker-news.firebaseio.com/v0')
5-
let cachedStoryIds = []
6-
const cachedStories = {}
6+
const itemsCache = Object.create(null)
77
const store = new EventEmitter()
88
const storiesPerPage = store.storiesPerPage = 30
99

10+
let topStoryIds = []
11+
1012
export default store
1113

1214
/**
1315
* Subscribe to real time updates of the top 100 stories,
1416
* and cache the IDs locally.
1517
*/
1618

17-
api.child('topstories').on('value', (snapshot) => {
18-
cachedStoryIds = snapshot.val()
19-
store.emit('update')
19+
api.child('topstories').on('value', snapshot => {
20+
topStoryIds = snapshot.val()
21+
store.emit('topstories-updated')
2022
})
2123

2224
/**
@@ -26,15 +28,17 @@ api.child('topstories').on('value', (snapshot) => {
2628
* @param {Function} cb(item)
2729
*/
2830

29-
store.fetchItem = (id, cb) => {
30-
if (cachedStories[id]) {
31-
cb(cachedStories[id])
32-
} else {
33-
api.child('item/' + id).once('value', function (snapshot) {
34-
const story = cachedStories[id] = snapshot.val()
35-
cb(story)
36-
})
37-
}
31+
store.fetchItem = id => {
32+
return new Promise((resolve, reject) => {
33+
if (itemsCache[id]) {
34+
resolve(itemsCache[id])
35+
} else {
36+
api.child('item/' + id).once('value', snapshot => {
37+
const story = itemsCache[id] = snapshot.val()
38+
resolve(story)
39+
}, reject)
40+
}
41+
})
3842
}
3943

4044
/**
@@ -44,19 +48,12 @@ store.fetchItem = (id, cb) => {
4448
* @param {Function} cb(items)
4549
*/
4650

47-
store.fetchItems = (ids, cb) => {
51+
store.fetchItems = ids => {
4852
if (!ids || !ids.length) {
49-
return cb([])
53+
return Promise.resolve([])
54+
} else {
55+
return Promise.all(ids.map(id => store.fetchItem(id)))
5056
}
51-
const items = []
52-
ids.forEach((id) => {
53-
store.fetchItem(id, (item) => {
54-
items.push(item)
55-
if (items.length >= ids.length) {
56-
cb(items)
57-
}
58-
})
59-
})
6057
}
6158

6259
/**
@@ -66,11 +63,11 @@ store.fetchItems = (ids, cb) => {
6663
* @param {Function} cb(stories)
6764
*/
6865

69-
store.fetchItemsByPage = (page, cb) => {
66+
store.fetchItemsByPage = page => {
7067
const start = (page - 1) * storiesPerPage
7168
const end = page * storiesPerPage
72-
const ids = cachedStoryIds.slice(start, end)
73-
store.fetchItems(ids, cb)
69+
const ids = topStoryIds.slice(start, end)
70+
return store.fetchItems(ids)
7471
}
7572

7673
/**
@@ -80,8 +77,10 @@ store.fetchItemsByPage = (page, cb) => {
8077
* @param {Function} cb(user)
8178
*/
8279

83-
store.fetchUser = (id, cb) => {
84-
api.child('user/' + id).once('value', (snapshot) => {
85-
cb(snapshot.val())
80+
store.fetchUser = id => {
81+
return new Promise((resolve, reject) => {
82+
api.child('user/' + id).once('value', snapshot => {
83+
resolve(snapshot.val())
84+
}, reject)
8685
})
8786
}

src/views/item-view.vue

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,42 +23,27 @@ import Item from '../components/item.vue'
2323
import Comment from '../components/comment.vue'
2424
2525
export default {
26-
components: {
27-
item: Item,
28-
comment: Comment
29-
},
3026
data () {
3127
return {
3228
item: {},
33-
pollOptions: null,
34-
comments: []
29+
comments: [],
30+
pollOptions: null
3531
}
3632
},
3733
route: {
3834
data ({ to }) {
39-
this.load(to.params.id)
35+
return store.fetchItem(to.params.id).then(item => ({
36+
item,
37+
comments: store.fetchItems(item.kids),
38+
pollOptions: item.type === 'poll'
39+
? store.fetchItems(item.parts)
40+
: null
41+
}))
4042
}
4143
},
42-
methods: {
43-
load (id) {
44-
store.fetchItem(id, (item) => {
45-
this.item = item
46-
this.fetchComments()
47-
if (item.type === 'poll') {
48-
this.fetchPollOptions()
49-
}
50-
})
51-
},
52-
fetchComments () {
53-
store.fetchItems(this.item.kids, (comments) => {
54-
this.comments = comments
55-
})
56-
},
57-
fetchPollOptions () {
58-
store.fetchItems(this.item.parts, (options) => {
59-
this.pollOptions = options
60-
})
61-
}
44+
components: {
45+
item: Item,
46+
comment: Comment
6247
}
6348
}
6449
</script>

src/views/news-view.vue

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
<item
55
v-for="item in items"
66
:item="item"
7-
:index="getItemIndex($index)"
7+
:index="$index | formatItemIndex"
88
track-by="id">
99
</item>
1010
<!-- navigation -->
1111
<div class="nav" v-show="items.length > 0">
12-
<a v-if="displayPage > 1" :href="'#/news/' + (displayPage - 1)">&lt; prev</a>
13-
<a v-if="displayPage < 4" :href="'#/news/' + (displayPage + 1)">more...</a>
12+
<a v-if="page > 1" :href="'#/news/' + (page - 1)">&lt; prev</a>
13+
<a v-if="page < 4" :href="'#/news/' + (page + 1)">more...</a>
1414
</div>
1515
</div>
1616
</template>
@@ -20,39 +20,41 @@ import store from '../store'
2020
import Item from '../components/item.vue'
2121
2222
export default {
23-
components: {
24-
item: Item
25-
},
2623
data () {
2724
return {
28-
displayPage: 1,
25+
page: 1,
2926
items: []
3027
}
3128
},
32-
created () {
33-
this.onUpdate = () => {
34-
this.update(this.$route.params.page)
35-
}
36-
store.on('update', this.onUpdate)
37-
},
38-
destroyed () {
39-
store.removeListener('update', this.onUpdate)
40-
},
4129
route: {
4230
data ({ to }) {
43-
this.update(to.params.page)
31+
const page = +to.params.page
32+
return store.fetchItemsByPage(page).then(items => ({
33+
page,
34+
items
35+
}))
4436
}
4537
},
38+
created () {
39+
store.on('topstories-updated', this.update)
40+
},
41+
destroyed () {
42+
store.removeListener('topstories-updated', this.update)
43+
},
4644
methods: {
47-
update (page) {
48-
store.fetchItemsByPage(page, (items) => {
45+
update () {
46+
store.fetchItemsByPage(this.page).then(items => {
4947
this.items = items
50-
this.displayPage = +page
5148
})
52-
},
53-
getItemIndex (index) {
54-
return (this.displayPage - 1) * store.storiesPerPage + index + 1
5549
}
50+
},
51+
filters: {
52+
formatItemIndex (index) {
53+
return (this.page - 1) * store.storiesPerPage + index + 1
54+
}
55+
},
56+
components: {
57+
item: Item
5658
}
5759
}
5860
</script>

src/views/user-view.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ export default {
2929
},
3030
route: {
3131
data ({ to }) {
32-
store.fetchUser(to.params.id, (user) => {
33-
this.user = user
34-
})
32+
return {
33+
user: store.fetchUser(to.params.id)
34+
}
3535
}
3636
}
3737
}

0 commit comments

Comments
 (0)