Skip to content

Commit 5d37389

Browse files
committed
feat(refs): wait for refs when resolving $bind promise
1 parent e963e54 commit 5d37389

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

src/index.js

+17-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createSnapshot, extractRefs } from './utils'
1+
import { createSnapshot, extractRefs, callOnceWithArg } from './utils'
22

33
function bindCollection ({
44
vm,
@@ -38,12 +38,14 @@ function bindCollection ({
3838
}, reject)
3939
}
4040

41-
function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0 }) {
41+
function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0, resolve }) {
4242
// TODO extract refs
4343
const [data, refs] = extractRefs(snapshot)
4444
obj[key] = data
45+
const refKeys = Object.keys(refs)
46+
if (!refKeys.length) resolve()
4547
// TODO check if no ref is missing
46-
Object.keys(refs).forEach(refKey => {
48+
refKeys.forEach(refKey => {
4749
// check if already bound to the same ref -> skip
4850
const sub = subs[refKey]
4951
const ref = refs[refKey]
@@ -56,7 +58,8 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0 }
5658
ref,
5759
obj: obj[key],
5860
key: refKey,
59-
depth: depth + 1
61+
depth: depth + 1,
62+
resolve
6063
}),
6164
path: ref.path
6265
}
@@ -67,13 +70,13 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0 }
6770
})
6871
}
6972

70-
function subscribeToDocument ({ ref, obj, key, depth }) {
73+
function subscribeToDocument ({ ref, obj, key, depth, resolve }) {
7174
// TODO max depth param, default to 1?
7275
if (depth > 3) throw new Error('more than 5 nested refs')
7376
const subs = Object.create(null)
7477
return ref.onSnapshot(doc => {
7578
if (doc.exists) {
76-
updateDataFromDocumentSnapshot({ snapshot: createSnapshot(doc), obj, key, subs, depth })
79+
updateDataFromDocumentSnapshot({ snapshot: createSnapshot(doc), obj, key, subs, depth, resolve })
7780
} else {
7881
obj[key] = null
7982
}
@@ -88,33 +91,25 @@ function bindDocument ({
8891
reject
8992
}) {
9093
// TODO warning check if key exists?
91-
// TODO create boundRefs object
9294
// const boundRefs = Object.create(null)
9395

94-
let ready
9596
const subs = Object.create(null)
97+
// bind here the function so it can be resolve anywhere
98+
// this is specially useful for refs
99+
resolve = callOnceWithArg(resolve, () => vm[key])
96100
return document.onSnapshot(doc => {
97101
if (doc.exists) {
98102
updateDataFromDocumentSnapshot({
99103
snapshot: createSnapshot(doc),
100104
obj: vm,
101105
key,
102-
subs
106+
subs,
107+
resolve
103108
})
109+
} else {
110+
resolve()
104111
}
105-
// TODO should resolve be called when all refs are bound?
106-
if (!ready) {
107-
ready = true
108-
resolve(vm[key])
109-
}
110-
// TODO bind refs
111-
// const d = doc.data()
112-
// if (!boundRefs[d.path]) {
113-
// console.log('bound ref', d.path)
114-
// boundRefs[d.path] = d.onSnapshot((doc) => {
115-
// console.log('ref snap', doc)
116-
// }, err => console.log('onSnapshot ref ERR', err))
117-
// }
112+
// TODO resolve when does not exist ?
118113
}, reject)
119114

120115
// TODO return a custom unbind function that unbind all refs

src/utils.js

+10
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,13 @@ export function extractRefs (doc) {
1919
return tot
2020
}, [{}, {}])
2121
}
22+
23+
export function callOnceWithArg (fn, argFn) {
24+
let called
25+
return () => {
26+
if (!called) {
27+
called = true
28+
return fn(argFn())
29+
}
30+
}
31+
}

test/bind.spec.js

+15
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,18 @@ test('unbinds previously bound refs', async () => {
8989
expect(vm.$firestoreRefs.item).toBe(doc2)
9090
expect(vm.item).toEqual({ bar: 'bar' })
9191
})
92+
93+
test('resolves the promise when refs are resolved in a document', async () => {
94+
const a = db.collection().doc()
95+
await a.update({ a: true })
96+
await document.update({ ref: a })
97+
98+
await vm.$bind('item', document)
99+
expect(vm.item).toEqual({ ref: { a: true }})
100+
})
101+
102+
test('resolves the promise when the document does not exist', async () => {
103+
expect(vm.item).toEqual(null)
104+
await vm.$bind('item', document)
105+
expect(vm.item).toBe(null)
106+
})

0 commit comments

Comments
 (0)