Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Using redux and angular 2 with meteor

166 visualizaciones

Publicado el

Slides from the Meteor Toronto Meet Up. September 21, 2016.

The session started with a cursory introductions of Angular 2 and Redux. We will then explored an experimental implementation of an Angular 2 Redux app with Meteor. A high level overview of the approach will be presented and then we will explore the source code guided by the curiosity of the group.

Publicado en: Software
  • Inicia sesión para ver los comentarios

Using redux and angular 2 with meteor

  1. 1. Using Redux and Angular 2 with Meteor Ken Ono Principal and CTO Fabrica Technology September 21, 2016
  2. 2. Introductions • Host Facility Introduction and Thanks • Attendee Intros – Recruiters or Recruiting? – Potentially available for hires – Individual Intros (First Name, Current Employer, Tech Interests, Experience with Meteor, Angular 2 or Redux) • About Ken – Current • Principal and CTO of Fabrica Technology (CTO for Hire) • VP Analytics @ TBA • CTO @ Aluvion Law – Formerly • CTO of Angoss Software (data mining) • VP Analytics and Innovation at NexJ Systems (enterprise CRM and consumer health and wellness) • CTO of Myant (Smart Garments). – Blog at: www.fabrica.tech
  3. 3. Agenda • Introductions • Introduction to Angular 2 • Introduction to Redux • Overview of an Approach for Meteor, Redux, Angular • Let’s Look at Code • Questions / deep dives at the end
  4. 4. Angular 2 - Important Prerequisites • ES6 • TypeScript • RxJS
  5. 5. ES6 – http://es6-features.org/ – Lambda / Arrow Function Syntax • function(x){} same as (x)=>{} • ()=>{1} same as ()=>{return 1} • a=>{a*2}; – Classes (prototypical inheritance) – `` strings – let / const (new scoping rules) – Extended Parameters • Defaults: (x, b=1)=>{} • Rest: (x,y, …a )=>{} (a is an array of remaining params) • Spread: [1, …[2,3]] same as [1,2,3] – Property Short Hand: • {x} same as {x:x} – Iterators & Generators – Import/export Modules
  6. 6. TypeScript – https://www.typescriptlang.org – Superset of ES6 – Compiles to ES5 (or 6) – Adds type checking, interfaces, generics and more – Decorators • annotating or modifying classes and class members • experimental, but heavily used by Angular 2 • http://rangle.io/resources/demystifying-decorators-a- new-feature-to-javascript/ export enum EDocumentChangeType { NEW, CHANGED, REMOVED, MOVED } export interface IDocumentChange<T> { changeType:EDocumentChangeType, newDocument?: T, oldDocument?: T, atIndex?:number, before?:string fromIndex?:number } … export class MeteorCursorObservers { static createCursorObserver<T>(ursor: Mongo.Cursor<any>): Observable<IDocumentChange<T>> { return Observable.create( (observer: Subscriber<IDocumentChange<T>>) => { let handle: Meteor.LiveQueryHandle = cursor.observe({ … Not your father’s JavaScript
  7. 7. RxJS – http://reactivex.io/ – Create and subscribe to streams – Observable • Like Promise except next(), error(), complete() – Library of operators make it like lodash/_, but for streams • Streams are like arrays, except over time, instead of indexed in memory – Declarative, not imperative – Hot (mouse clicks/live play) vs Cold (server request/DVD) – Will be part of JavaScript (currently stage one proposal) let myObservable<MyType> = somthingThatGivesMeAnObservable(); let subscription:Subscription = myObservablle.subsribe( (myData:MyType)=>{}, // Data pushed to you from Observable ()=>{}, // Error ()=>{} // Complete ); subSrciption.unsubscribe(); … myObservable.map( funciton (myData:MyType) { return transformed(myData); }). … // Short hand: myObservable.map( myData:MyType=> transformed(myData));
  8. 8. Key Angular 2 Features • Components and Directives – Hierarchical tree of components – Properties in / Events out – Templating, two-way binding and built in directives – Life Cycle Events • Forms • Services – HTTP – Router • Pipes • Dependency Injection • Testing • Animation • Modules • Web Workers • Client options (Bootstrap, Angular Material, Ionic (Native look and feel with Cordova), NativeScript (Angular 2 & JS with iOS and Android native components - No DOM), Angular Universal, Electron (browser and Node bundle for desktop) • CLI • https://angular.io/docs/ts/latest/guide/cheatsheet.html • http://rangle.io/resources/intro-to-angular-2-components/
  9. 9. Redux • A central nervous system for events and actions to derive a clean, well-defined application state. • A New Way of Organizing Code that is simple to conceptualize: – Actions (that have an action type and payload) are fired, – A reducer computes a new state with pure functions given an action and current state, – Middleware handles anything asynchronous (actions in, actions out) UI Actions Reducer StateStateStateState Middle ware Putting Redux into practice is a mental adjustment Yuri Takhteyev, CTO of Rangle, intro to Redux https://www.youtube.com/watch?v=s9AC8KTcce8
  10. 10. Redux Module • My approach to organizing Redux pieces • Define a reducer, set of actions and async handlers as a bundle • Let’s look at a few modules that map to Meteor features – Organizing Actions – Updating State – Async and connecting to Meteor services – Connecting to Angular Components export abstract class ReduxModule<T> { reducer:Reducer<T>; epics:Epic[]=[]; // Stream based middleware middlewares:any[]=[]; // Normal redux middleware enhancers:any[]=[]; actions:Object; abstract initialize():void; } …
  11. 11. Patterns • Request, Manage, Respond, Listen – a Redux Pattern – Kick off a request action – Middleware reacts to the request and kicks off server call. (Promises and RxJS to manage the asynchronous events.) – Server returns data (a single response or many responses from a watch) – Response action fired with data from server (or error condition) – Your reducer updates the application state with the new data – Presentation components wait for the information they need to arrive • Write and Watch - a Meteor/Redux Pattern – Write data to a Mongo Collection (via Collection.insert, Meteor.method) – Observe changes
  12. 12. Meteor – Cursor.observe • Mongo.Cursor#observe – Watch a query. Receive callbacks as the result of Mongo query changes. – Callbacks for • Added(document) or • Changed(newDocument, oldDocument) or • Removed(oldDocument) • http://docs.meteor.com/api/collections.html#Mongo-Cursor-observe
  13. 13. Wrapping a Meteor Cursor with an Observable • Convert a reactive Meteor cursor to an Observable: fromMeteorCursor<T>(cursor: Mongo.Cursor<any>): Observable<IDocumentChange<T>> { return Observable.create((observer: Subscriber<IDocumentChange<T>>) => { let handle: Meteor.LiveQueryHandle = cursor.observe({ added: (doc: T) => { observer.next({ changeType: EDocumentChangeType.NEW, newDocument: doc }); }, changed: (nDoc: T, oDoc: T) => { observer.next({ changeType: EDocumentChangeType.CHANGED, newDocument: nDoc, oldDocument: oDoc }); }, removed: (doc: T) => { observer.next({ changeType: EDocumentChangeType.REMOVED, • Then observe the cursor: static createUserObserver(userId:string):Observable<IDocumentChange<User>> { return MeteorCursorObservers. fromMeteorCursor<User>( Meteor.users.find({_id: userId}) ); } .createUserObserver(LoginService.userId()).map( (change:IDocumentChange<User>)=>{ let loginState:ILoginState = store.getState().loginReducer; if (loginState && loginState.neverLoggedIn) { // Never logged in, yet the current user is populated, must be automatic login return LoginActions.loginSuccessFactory( change.newDocument, change.newDocument._id, true); } else { return LoginActions.changeFactory(change); } })
  14. 14. Other Important Packages • Immutable.js - new state generation – Provides immutable maps and arrays (and more) – https://facebook.github.io/immutable-js/ – https://www.youtube.com/watch?v=I7IdS-PbEgI • NgRedux - Angular bindings for Redux – @select decorators, injectable store and dispatcher – https://github.com/angular-redux/ng-redux – https://www.youtube.com/watch?v=s4xr2avwv3s • Redux-Observable - RxJS middleware – Use RxJS operators (.filter, .map, .flatMap) for async operations – https://github.com/redux-observable/redux- observable var Immutable = require('immutable'); var map1 = Immutable.Map({a:1, b:2, c:3}); var map2 = map1.set('b', 50); map1.get('b'); // 2 map2.get('b'); // 50 @Component(…) class App { @select() count$: Observable<number>; constructor(private ngr: NgRedux<IAppState>) {} onClick() { this.ngr.dispatch({ type: INC); } } const pingEpic = action$ => action$.filter(action => action.type === 'PING') .delay(1000) // wait 1000ms .mapTo({ type: 'PONG' }); // later... dispatch({ type: 'PING' });
  15. 15. Demo App • For Real Cards (attempts to mimic actual card, game engine does not know rules) • Source Code: https://github.com/kokokenada/for-real-cards • Hosted at: http://for-real-cards.scalingo.io/ • Mobile app: Search for ”for real cards Fabrica”
  16. 16. Conclusion • Impact to Code – Reduced boiler plate (compared to using RxJS for actions) – Consolidated logic, less spaghetti code – Clean separation of presentation and data acquisition – Way, way easier to debug – Easier to develop rich functionality and reason about state and events – State is solidly understood – Less deep nesting / micro-management of async calls – Simple undo • Challenges – New way of thinking an organizing code – Lots of prerequisites to learn – Getting immutability right (for complex structures) takes practice – Tooling is catching up It’s hard work, but it will pay off

×