4

I've been experimenting with feathersjs and angular2/Rx. What I'm trying to achieve is building an angular2 service that's wrapping a feathersjs service in such a way that one can just subscribe to an Observable that emits an up-to-date set of items after any kind of CRUD.

It basically works. However, I don't find the way it's done very elegant: Wrapping and unwrapping every object that's coming in doesn't seem efficient. Am I taking 'Everything's a stream' too far?

getService(){
let data$: Observable<any> = Observable.from([initialSetOfItems]);
let created$: Observable<any> = Observable.fromEvent(feathersService, 'created').map(o => {return {action: 'c', data: o}});
let updated$: Observable<any> = Observable.fromEvent(feathersService, 'updated').map(o => {return {action: 'u', data: o}});
let removed$: Observable<any> = Observable.fromEvent(feathersService, 'removed').map(o => {return {action: 'r', data: o}});

return data$
  .merge(created$, updated$, removed$)
  .scan((arr: any[], newObj) => {
    switch (newObj.action){
      case 'c':
        return [].concat(arr, newObj.data);

      case 'u':
        let indexToUpdate = arr.findIndex((element) => (element.id === newObj.data.id));
        if (indexToUpdate > -1){
          arr[indexToUpdate] = newObj.data;
        }
        return arr;

      case 'r':
        return arr.filter(element => (element.id != newObj.data.id))
    }
  });
}

I know this might be opinionated. Please bear with me. Rx is a little hard to wrap your head around.

How would you guys try to achieve this?

j2L4e
  • 6,914
  • 34
  • 40
  • 1
    that's how I'd do it. Except for your update case where you are actually modifying the array in place...I recommend cloning the array before applying the update. – Brandon Jun 09 '16 at 18:33
  • You're right, thanks! – j2L4e Jun 10 '16 at 10:22

1 Answers1

3

I think what you are looking for is exactly what feathers-reactive is supposed to do. It is a plugin that turns any service method into an RxJS observable that automatically updates on real-time events. It can be used like this:

const feathers = require('feathers');
const memory = require('feathers-memory');
const rx = require('feathers-reactive');
const RxJS = require('rxjs');

const app = feathers()
  .configure(rx(RxJS))
  .use('/messages', memory());

const messages = app.service('messages');

messages.create({
  text: 'A test message'
}).then(() => {
  // Get a specific message with id 0. Emit the message data once it resolves
  // and every time it changes e.g. through an updated or patched event
  messages.get(0).subscribe(message => console.log('My message', message));

  // Find all messages and emit a new list every time anything changes
  messages.find().subscribe(messages => console.log('Message list', messages));

  setTimeout(() => {
    messages.create({ text: 'Another message' }).then(() =>
      setTimeout(() => messages.patch(0, { text: 'Updated message' }), 1000)
    );
  }, 1000);
});

If you want to give it a try, we would love to get some feedback (and bug reports).

Daff
  • 43,734
  • 9
  • 106
  • 120