getting started feature roadmap faq
use cases pricing
developers
company
enterprise contact

Getting started with deepstreamHub is easy and takes less than ten minutes. However, if you have any questions, please get in touch.

This getting started guide will walk you through integrating deepstream in Ionic (v2x).

Ionic is built on top Angular so you will see a lot of borrowed code from the Angular guide. This means we might interchange the words Angular and Ionic.

You will also learn how to implement the three deepstream core concepts: Records, Events and RPCs.

First, let's start by creating a free deepstreamHub account:

Create a free account and get your API key

deepstream provides a JavaScript library which helps in interacting with your deepstreamHub server.

Create an Ionic App

Install the Ionic CLI tool globally and use the tool to scaffold a new app:

# Install CLI tool
npm install -g ionic
# Scaffold a new app
ionic start ds-ionic tabs --v2

tabs is the template we want to use and --v2 is the preferred Ionic version

Connect to deepstreamHub and log in

After you have successfully created an Angular app install the deepstream and the JS-client library in your new project:

npm install deepstream.io-client-js --save

We need to import deepstream to our Ionic app:

import * as deepstream from 'deepstream.io-client-js';

Get your app url from the dashboard and establish a connection to deepstreamHub using an Angular service:

@Injectable()
export class DsService {
  get dsInstance() {
    return deepstream('<YOUR APP URL>').login()
  }
}

The login method can take credentials if authentication is configured.

Records (realtime datastore)

Records are the documents in deepstreamHub’s realtime datastore. A record is identified by a unique id and can contain any kind of JSON data. Clients and backend processes can create, read, write, update and observe the entire record as well as paths within it. Any change is immediately synchronized amongst all connected subscribers.

Records can be arranged in lists and collections and can contain references to other records to allow for the modelling of relational data structures.

You can learn more about records in the records tutorial.

Creating a new record or retrieving an existent one works the same way:

var myRecord = ds.record.getRecord( 'test/johndoe' );

Values can be stored using the .set() method:

myRecord.set({
    firstname: 'John',
    lastname: 'Doe'
});

Let's set up two-way bindings with an input field. Whenever a path within our record changes (e.g. firstname), we want to update the input. Whenever a user types, we want to update the record.

Two-way realtime bindings

Let's see a contexual example:

@Component({
  selector: 'page-record',
  template: `
  . . .
      <ion-list>

    <ion-item>
      <ion-label floating>First Name</ion-label>
      <ion-input type="text" [ngModel]="firstname" (ngModelChange)="handleFnameChange($event)"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label floating>Last Name</ion-label>
      <ion-input type="text" [ngModel]="lastname" (ngModelChange)="handleLnameChange($event)"></ion-input>
    </ion-item>

  </ion-list>
  . . .
  `
})
export class RecordPage implements OnInit{
  firstname;
  lastname;
  record;

  constructor(private dsService: DsService){}

  ngOnInit() {
    this.record = this.dsService.dsInstance.record.getRecord('test/johndoe')
    this.record.subscribe((val) => {
      this.firstname = val.firstname;
      this.lastname = val.lastname;
    })
  }

  handleFnameChange(val){
    this.record.set('firstname', val);
  }
  handleLnameChange(val) {
    this.record.set('lastname', val);
  }
}

The subscribe method is used to listen for updates and update the inputs accordingly. The method is called in the ngOnInit lifecycle hook so it can be setup once the component is loaded.

Events (publish-subscribe)

Events are deepstreamHub’s publish-subscribe mechanism. Clients and backend processes can subscribe to event-names (sometimes also called “topics” or “channels”) and receive messages published by other endpoints.

Events are non-persistent, one-off messages. For persistent data, please use records.

Publish-Subscribe

Clients and backend processes can receive events using .subscribe()

ds.event.subscribe( 'test-event', function( eventData ){ /*do stuff*/ });

... and publish events using .emit()

ds.event.emit( 'test-event', {some: 'data'} );

A little example:

@Component({
  selector: 'page-events',
  template: `
  ...
    <ion-content padding>
  <ion-list>
    <ion-item>
      <ion-label stacked>Value</ion-label>
      <ion-input type="text" [(ngModel)]="value"></ion-input>
    </ion-item>

    <ion-item>
      <button ion-button (click)="handleClick()">Send</button>
    </ion-item>
  </ion-list>

  <ion-list>
    <ion-list-header>Events Received</ion-list-header>
    <ion-item *ngFor="let event of eventsReceived">
      <ion-icon name="megaphone" item-left></ion-icon>

    </ion-item>
  </ion-list>

</ion-content>
...
  `
})
export class EventsPage implements OnInit {
  value = '';
  eventsReceived = [];

  constructor(private dsService: DsService){}

  ngOnInit() {
    this.dsService.dsInstance.event.subscribe('test-event', (val) => {
      this.eventsReceived.push(val);
    })
  }

  handleClick() {
    console.log(this.value)
    this.dsService.dsInstance.event.emit('test-event', this.value);
  }
}

An event is published anytime the button is clicked and the event.subscribe method listens for this publish action.

RPCs (request-response)

Remote Procedure Calls are deepstreamHub’s request-response mechanism. Clients and backend processes can register as “providers” for a given RPC, identified by a unique name. Other endpoints can request said RPC.

deepstreamHub will route requests to the right provider, load-balance between multiple providers for the same RPC, and handle data-serialisation and transport.

Request Response

You can make a request using .make()

ds.rpc.make( 'multiply-numbers', { a: 6, b: 7 }, function( err, result ){
    //result === 42
});

and answer it using .provide():

ds.rpc.provide( 'multiply-numbers', function( data, response ){
    resp.send( data.a * data.b );
});

For example:

@Component({
  selector: 'page-rpc',
  template: `
    <ion-list>

    <ion-item>
      <ion-label fixed>Request</ion-label>
      <ion-input type="text" [(ngModel)]="requestValue"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label fixed>Response</ion-label>
      <ion-input type="text" [(ngModel)]="responseValue"></ion-input>
    </ion-item>

    <ion-list-header></ion-list-header>

    <ion-item>
      <button ion-button (click)="handleClick()">Make</button>
    </ion-item>

  </ion-list>
  `
})
class RPCPage implements OnInit {
  requestValue = '3';
  responseValue = '7';
  displayResponse = '-';

  constructor(private dsService: DsService){}

  handleClick() {
          var data = {
                value: parseFloat(this.requestValue)
            };
        this.dsService.dsInstance.rpc.make( 'multiply-number', data, ( err, resp ) => {

              //display the response (or an error)
              this.displayResponse = resp || err.toString();
          });
  }

  ngOnInit() {
    this.dsService.dsInstance.rpc.provide( 'multiply-number', ( data, response ) => {
          // respond to the request by multiplying the incoming number
          // with the one from the response input
          response.send( data.value * parseFloat(this.responseValue) );
    })
  }
}

Clicking the button makes a request using rpc.make. The .make method is also responsible for handling the responses when they come back from the response provider which is the rpc.provide method.

Where to go next?

To learn how to use deepstreamHub with other frontend frameworks head over to the tutorial section. To learn how to use the JavaScript SDK with NodeJS rather than in a browser, head over to the getting started with NodeJS tutorial.