vuefire icon indicating copy to clipboard operation
vuefire copied to clipboard

Automatically expose promises when using firestore option

Open franciscolourenco opened this issue 5 years ago • 7 comments

It would be useful to be able to use the short firestore notation and still be able to access the promises, for usage with vue-promised for instance.

There are not a lot of situation where data is loaded asynchronously, and a loader indicator is not necessary.

i.e.

<template>
  <Promised :promise="$firestore.promised.todos">
	<!-- etc... -->
  </Promised>

  <Promised :promise="$firestore.promised.currentTodo">
	<!-- etc... -->
  </Promised>
</template>


<script>
new Vue({
  data: {
    // Usually an array for collection
    todos: [],
    // and null for documents
    currentTodo: null,
  },
  firestore: {
    todos: db.collection('todos'),
    currentTodo: db.collection('todos').doc('1'),
  },
})
</script>

franciscolourenco avatar Mar 11 '19 12:03 franciscolourenco

I have thought about this before but I'm not convinced at all because it can already be achieved:

new Vue({
  data: {
    // Usually an array for collection
    todos: [],
    // and null for documents
    currentTodo: null,
    todosPromise: null,
    currentTodoPromise: null,
  },
  created () {
    this.todosPromise = this.$bind('todos', db.collection('todos'))
    this.currentTodoPromise = this.$bind('currentTodo', db.collection('todos').doc('1'))
  },
})

It also works pretty well with a computed property which also works for automatic rebinding

computed: {
  currentTodo: vm => vm.$bind('currentTodo', db.collection('todos').doc(vm.currentTodoId))
}

Also, in SSR one would wait for the promise directly.

posva avatar Mar 11 '19 12:03 posva

2 thoughs:

  1. If we use the same line of reasoning, we should question the existence of the firestore option in the first place. If we deem the firestore option useful enough to be included in the library, it should be complete and convenient enough that it supports the most basic use cases, like displaying loading states.
  2. Having the promises directly in the model, next to the actual data (i.e. todosPromise), looks slightly out of place because they are more like internals/metadata. It would be nicer to have them in a namespace like $firestore or something.

PS: Excuse my ignorance but in which situations is the automatic rebinding useful? Thanks!

franciscolourenco avatar Mar 11 '19 13:03 franciscolourenco

Why would we want to use promises instead of async/await?

pacific202 avatar Apr 01 '19 09:04 pacific202

It's the same thing

franciscolourenco avatar Apr 01 '19 09:04 franciscolourenco

I apologize, my last question was rhetorical. It would seem like a step backwards (sideways at best) to put effort into supporting promises in the exposed API when the JavaScript world is moving from callbacks to async/await.

This is the context that statement was meant to be taken in:

https://getstream.io/blog/javascript-promises-and-why-async-await-wins-the-battle/

pacific202 avatar Apr 01 '19 09:04 pacific202

I believe that what we're looking for is something parallel to the AngularFire $loaded event.

The computed method above works for me for now, but in future I'd like a single event to be fired when all vuefire promises have been resolved without the developer having to replicate all of the individual data variable names in a computed or created and maintain that list in two sections of the component.

I'd like to see this implemented as a vue lifecycle function that would get called when all vuefire calls have returned:

{
  data: function(){
    return {
      a: null,
      b: []
    }
  },
  firestore: {
     a: db.get('a'),
     b: db.collection('b')
  },
  firestore_loaded: function([err]) {
    // need to figure out the best way to trap zero or more errors here
  }
}

pacific202 avatar Apr 16 '19 20:04 pacific202

😄

franciscolourenco avatar Apr 16 '19 23:04 franciscolourenco

FYI this is now possible with the composables useDocument() and others

posva avatar Dec 21 '22 14:12 posva