3
\$\begingroup\$

I'm doing a prototype of server API calls in my Ionic (Angular) application. I'm considering this use case:

@IonicPage({/* */})
@Component({/* */})
export class SomePage {
  constructor(private api: Api) { }

  ngOnInit() {
    this.api.user.getList();
  }
}

To achieve this I have something like this:

@Injectable()
export class Api {
  constructor(
    public user: UserApi,
    public event: EventApi,
    public search: SearchApi
  ) {

  }
}

@Injectable()
export class UserApi extends BaseApi {
  private static readonly ENDPOINT: string = "user/";

  constructor(public http: HttpClient) {
    super(UserApi.ENDPOINT);
  }

  getList() {
    return this.http.get(this.url);
  }
}

export class BaseApi {
  private host: string = "https://my-site.com/api/";
  protected url: string;

  constructor(endpoint: string) {
    this.url = this.host + endpoint;
  }
}

Next purposes:

  • Separate API Service from others Servicies
  • Split one API Service to little parts where each one works with single essence

And I have a few questions about my approach:

  • Are there any pitfalls in this approach?
  • Is this a "good" approach to organize API calls? What can I improve or do in another way?
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Your approach is already pretty good.

What I would do to improve your code is the following:

  • Use a config/constants.ts file for your constants.
  • Generate two providers (using ionic g provider <providername>).
  • In the first provider put all the route related code (I always call it server-communication.ts).
  • In the second provider put all the logic (I always call it app-data.ts).
  • Import the second provider in all the pages where it is needed.

Here is short example:

constants.ts:

/*
 * SERVER
 */
export const AUTH = "Authorization",
  TOKEN_PREFIX = "Token ",
  SERVER_ADDRESS = "https://myserver.com/api/";
/*
 * ROUTES
 */
export const ROUTE_LOGIN = "login/",
  ROUTE_FACEBOOK = "social/facebook/",
  ROUTE_REGISTER = "register/";
// Go on with all the other constants you might need.

server-communication.ts:

import { Injectable } from "@angular/core";
import { Http, Headers, RequestOptions } from "@angular/http";
import "rxjs/add/operator/map";

import {
  SERVER_ADDRESS,
  TOKEN_PREFIX,
  ROUTE_LOGIN,
  ROUTE_FACEBOOK,
  ROUTE_REGISTER
} from "../../config/constants";

@Injectable()
export class ServerCommunicationProvider {
  constructor(private http: Http) {}

authenticate(credentials) {
    return this.http
      .post(SERVER_ADDRESS + ROUTE_LOGIN, credentials)
      .map(res => res.json());
  }

  registerUser(credentials) {
    return this.http
      .post(SERVER_ADDRESS + ROUTE_REGISTER, credentials)
      .map(res => res.json());
  }
  // Go on with your other routes.

  // If you need to specify more data about the request do it like this:
  getObject(objectID: number): Promise<any> {
    return new Promise((resolve, reject) => {
      this.http
        .get(SERVER_ADDRESS + ROUTE_OBJECT + objectId, this.getHttpHeader())
        .subscribe(
          data => {
            resolve(data.json());
          },
          err => {
            console.log(err);
            reject(err);
          }
        );
    });
  }

  //Getting the correct format for the authorization header
  getHttpHeader(): RequestOptions {
    return new RequestOptions({
      headers: new Headers({
        Authorization: TOKEN_PREFIX + this.storageProv.userToken,
        "content-Type": "application/json",
        Accept: "application/json"
      })
    });
  }

And then utilize those appdata.ts:

import { Injectable } from "@angular/core";
import { ServerCommunicationProvider } from "../server-communication/server-communication";

@Injectable()
export class AppDataProvider {
  constructor(
    private serverProv: ServerCommunicationProvider
  ) {}

login(email: string, password: string): void {
    this.loadingProv.authLoading();
    let credentials = {
      username: email,
      password: password
    };
    this.serverProv.authenticate(credentials).subscribe(
      res => {
      // Your login logic here
      },
      err => {
      // What happens when user can't log in here.
      }
    );
  }
  // More functions with logic for your routes.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.