内容简介:Firebase provides realtime streams and async callbacks to do all sorts of awesome things in your app. Getting data from one realtime stream is easy enough, but what if you want to join it from another? Combining multiple async streams of data can get comp
Source: Introducing RxFire: Easy async Firebase for all frameworks from Firebase
Firebase provides realtime streams and async callbacks to do all sorts of awesome things in your app. Getting data from one realtime stream is easy enough, but what if you want to join it from another? Combining multiple async streams of data can get complex. At Firebase, we wanted to help simplify things, so we created a new JavaScript library: RxFire .
RxJS + Firebase
RxJS is a popular JavaScript library that simplifies async streams of data. The core component of RxJS is the observable. The observable is a mechanism for observing data as it changes over time. RxJS allows you to transform the changes as they occur with array like operators such as map and filter. This works magically with Firebase.
RxJS is a powerful toolkit for observing and transforming data streams. Firebase provides multiple types of data streams. Combine the two and you have a simple way of managing async data across multiple Firebase streams. Need to get data from an authenticated user? Want to join two records in Firestore? Want to lazy load the Firebase SDK with Webpack? This is the magic we’re talking about. We wanted to capture this magic in a library: RxFire.
Introducing RxFire
RxFire provides a set of observable creation methods. You simply call a function with some parameters to receive an RxJS observable. With that observable in hand you can use any operators provided by RxJS to transform the stream as you like.
The observable has a .pipe()
method that is used to attach operators. This is really similar to an array. You can .map()
and .filter()
, but the magic is that as data comes in over time it is ran through these operators. This is great for situations where you want to listen for when a user logs in.
import firebase from 'firebase/app'; import 'firebase/auth'; import { authState } from 'rxfire/auth'; import { filter } from 'rxjs/operators'; const app = firebase.initializeApp({ /* config */ }); authState(app.auth()) .pipe( filter(u => u !== null) ).subscribe(u => { console.log('the logged in user', u); });
The code above uses RxFire to listen to authentication state. The .filter()
operator checks for an authenticated user. The .subscribe()
callback is triggered only if a user is present.
Simplify common Firebase tasks
RxFire also includes helpful functions for common Firebase tasks. Do you need a synchronized array of child events in the Realtime Database? You’re just one function call away!
import firebase from 'firebase/app'; import 'firebase/database'; import { list } from 'rxfire/database'; const app = firebase.initializeApp({ /* config */ }); const todosRef = app.database().ref('todos'); list(todosRef).subscribe(list => { console.log('a synchronized array!', list); });
Events occurring on the todoRef
trigger the subscribe callback with a new array.
For all frameworks
The idea of mixing RxJS and Firebase together is not revolutionary or unique. The officially supported AngularFire library heavily uses RxJS with Firebase. We took the lessons we learned from over two years of development and ported it out so all frameworks could benefit. It doesn’t matter if you’re using React , Preact , Vue , Stencil , Polymer , or just plain old JavaScript. RxFire is setup to be a simple library to simplify the Firebase streams. Just look at this simple Preact component.
import { Component, h } from 'preact'; import firebase from 'firebase/app'; import 'firebase/firestore'; import { collectionData } from 'rxfire/firestore'; export class AppComponent extends Component { componentWillMount() { this.app = firebase.initializeApp({ /* config */ }); this.todosRef = app.firestore().collection('todos'); collectionData(todosRef, 'id').subscribe(todos => { // re-render on each change this.setState({ todos }); }); } render() { const lis = this.state.todos.map(t => <li key={t.id}>{t.title}</li>); return ( <div> <ul> {lis} </ul> </div> ); } }
The component renders new list items each time the collection data changes.
Build you own library with RxFire
Notice that RxFire isn’t a complete wrapper for Firebase and RxJS, rather it works in a complementary fashion. This makes is easy to sprinkle in to existing applications or even build new integrations.
Let’s say you want to create an idiomatic library for your app or framework. You can use RxFire as a base layer and let it do the heavy lifting for you. All you have to do is place your own API on top of it instead of worrying about complex tasks like synchronizing multiple events into a single array.
Combine multiple data sources
A common task is joining data in either the Realtime Database or Firestore. This is difficult because you’re trying to wrangle data from multiple callbacks. Each callback can trigger at different times and it becomes a strain to figure out what’s going on.
RxFire simplifies combining multiple data sources. You don’t have to worry about nested callbacks or wrangling variables that are out-of-scope. All you need to do is use RxJS’s observable combination methods like merge
or combineLatest
. In fact, combineLatest
works just like a join.
import firebase from 'firebase/app'; import 'firebase/firestore'; import { collectionData, docData } from 'rxfire/firestore'; import { combineLatest } from 'rxjs'; const app = firebase.initializeApp({ /* config */ }); // Create observables of document and collection data const profile$ = docData(app.firestore().doc('users/david')); const cart$ = collectionData(app.firestore().collection('carts/david')); const subscription = combineLatest(profile$, cart$, (profile, cart) => { // transform the profile to add the cart as a child property profile.cart = cart; return profile; }) .subscribe(profile => { console.log('joined data', profile); }); // Unsubscribe to both collections in one call! subscription.unsubscribe();
The combineLatest
method waits for each observable to fire once. It then triggers the subscription callback each time a change occurs to either the profileRef
or cartRef
. The last argument allows you to transform the data into a single object, making joins much easier.
Retrieving data from an authenticated user is another common task that traditionally required nested callbacks. RxJS allows you to get one piece of data asynchronously and then use that to conditionally get another. In this case you can check for an authenticated user and then retrieve a photo from Cloud Storage based on the user’s id.
import firebase from 'firebase/app'; import 'firebase/auth'; import 'firebase/storage'; import { authState } from 'rxfire/auth'; import { getDownloadURL } from 'rxfire/storage'; import { switchMap, filter } from 'rxjs/operators'; const app = firebase.initializeApp({ /* config */ }); authState(app.auth()) .pipe( filter(u => u !== null), switchMap(u => { const ref = app.storage().ref(`profile/${u.uid}`); return getDownloadURL(ref): }); ).subscribe(photoURL => { console.log('the logged in user's photo', photoURL); });
The code above listens for the authenticated users and filters out any logged out or null events. When there is an authenticated user, we get their photo URL based on the logged in user’s id.
Simplify code-splitting of Firebase
Modern web tools like Webpack provide advanced tooling like code-splitting. Code-splitting is an easy way to lighten the load of your application’s core code. The idea is to keep only what’s needed in the core of the application and load the rest only when needed. This is achieved by using the dynamic import() statement .
document.querySelector('#btnLoadFirebase') .addEventListener('click', event => { // load Firebase only when this button is clicked! import('firebase/app') .then(firebase => { console.log('lazy loaded!' }); });
Webpack is super smart and takes the lazily loaded module ( 'firebase/app'
in this case) and splits it out into a separate file. This is a huge benefit for performance because it lightens to amount of JavaScript the browser has to load upfront.
While this technique is great for performance, it’s really tricky to get right. You may have to load multiple libraries and deal with multiple async callbacks. RxFire makes this much easier. Using RxFire you can simplify the loading The dynamic import()
uses promises, but RxJS makes it easy to convert promises to observables.
import { from, combineLatest } from 'rxjs'; import { map, mergeMap } from 'rxjs/operators'; function lazyLoadCollection(config, collectionName) { const app$ = from(import('firebase/app')); const firestore$ = from(import('firebase/firestore')); const rxfire$ = from(import('rxfire/firestore')); return combineLatest(app$, firestore$, rxfire$) .pipe( map(([firebase, firestore, rxfire]) => { const app = firebase.apps[0] || firebase.initializeApp(config); return { app, rxfire }; }), mergeMap(([app, rxfire]) => { const ref = app.firestore().collection(collectionName); return rxfire.collectionData(ref, 'id'); }) ); } document.querySelector('#btnLoadTodos') .addEventListener('click', event => { lazyLoadCollection({ /* config */ }, 'todos').subscribe(todos => { console.log('lazy todos!', todos); }); });
The sample above creates a stream of todos from Firestore while lazily loading Firebase, RxFire, and RxFire on a button click. This type of code is still more complex that we’d like, but RxFire is in beta and we’re working on making this much easier.
Give it a try!
We’d love for you to kick the tires on RxFire. Give it an install on npm or yarn. Make sure to include Firebase and RxJS as they are peer dependencies.
npm i rxfire firebase rxjs # or yarn add rxfire firebase rxjs
RxFire is in beta. We really value your feedback in any form. File issues or feature requests on Github and even contribute your own ideas and code! We’re really excited to see what you’ll do with RxFire.
除非特别声明,此文章内容采用 知识共享署名 3.0 许可,代码示例采用 Apache 2.0 许可。更多细节请查看我们的 服务条款 。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python Cookbook 中文版,第 3 版
David M. Beazley、Brian K. Jones / 陈舸 / 人民邮电出版社 / 2015-5-1 / 108.00元
《Python Cookbook(第3版)中文版》介绍了Python应用在各个领域中的一些使用技巧和方法,其主题涵盖了数据结构和算法,字符串和文本,数字、日期和时间,迭代器和生成器,文件和I/O,数据编码与处理,函数,类与对象,元编程,模块和包,网络和Web编程,并发,实用脚本和系统管理,测试、调试以及异常,C语言扩展等。 本书覆盖了Python应用中的很多常见问题,并提出了通用的解决方案。......一起来看看 《Python Cookbook 中文版,第 3 版》 这本书的介绍吧!
Markdown 在线编辑器
Markdown 在线编辑器
RGB HSV 转换
RGB HSV 互转工具