JMac JMac - 7 months ago 145
Javascript Question

How do you substitute HttpClient in Aurelia?

I'm brand new to Aurelia.

How would you change the following code to provide a dummy HttpClient, e.g. a json reader instead that would provide just a static set of json data, negating the need for a server in development.

import {inject} from 'aurelia-framework';
import {HttpClient} from 'aurelia-fetch-client';

@inject(HttpClient)
export class Users {
heading = 'Github Users';
users = [];

constructor(http) {
http.configure(config => {
config
.useStandardConfiguration()
.withBaseUrl('https://api.github.com/');
});

this.http = http;
}

activate() {
return this.http.fetch('users')
.then(response => response.json())
.then(users => this.users = users);
}
}

Answer

There's a couple steps required to get the demo code in your original post to a state where we can substitute HttpClient implementations.

Step 1

Remove the configuration code in the class's constructor...

These lines:

users.js

...
http.configure(config => {
  config
    .useStandardConfiguration()
    .withBaseUrl('https://api.github.com/');
});
...

Should move to the main.js file:

main.js

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging();

  configureContainer(aurelia.container);  // <--------

  aurelia.start().then(a => a.setRoot());
}

function configureContainer(container) {
  let http = new HttpClient();
  http.configure(config => {
    config
      .useStandardConfiguration()
      .withBaseUrl('https://api.github.com/');
  });
  container.registerInstance(HttpClient, http); // <---- this line ensures everyone that `@inject`s a `HttpClient` instance will get the instance we configured above.
}

Now our users.js file should look like this:

users.js

import {inject} from 'aurelia-framework';
import {HttpClient} from 'aurelia-fetch-client';

@inject(HttpClient)
export class Users {
  heading = 'Github Users';
  users = [];

  constructor(http) {
    this.http = http;
  }

  activate() {
    return this.http.fetch('users')
      .then(response => response.json())
      .then(users => this.users = users);
  }
}

Step 2:

Mock the HttpClient.

The user.js module only uses the fetch method which returns a Response object that has a json method. Here's a simple mock:

let mockUsers = [...todo: create mock user data...];

let httpMock = {
  fetch: url => Promise.resolve({
    json: () => mockUsers
  })
};

Step 3:

Reconfigure the container to use the http mock:

In step 1 we added a configureContainer function to the main.js module that registered a configured HttpClient instance in the container. If we wanted to use our mock version the configureContainer function would change to this:

main.js

...

let mockUsers = [...todo: create mock user data...];

let httpMock = {
  fetch: url => Promise.resolve({
    json: () => mockUsers
  })
};

function configureContainer(container) {      
  container.registerInstance(HttpClient, httpMock);
}

More info on configuring the container here: https://github.com/aurelia/dependency-injection/issues/73

Comments