2

I'm trying to write a simple web interface for Elasticsearch using Angular 2 and the official elasticsearch.js client from npm.

I've created a service like this:

import { Injectable } from '@angular/core';
import { Client } from 'elasticsearch';

@Injectable()
export class ElasticsearchService {

    private _client: Client;
    constructor() {
        if (!this._client) {
            this._connect();
        }
    };
    private _connect() {
        this._client = new Client({
            host: 'http://my-elasticsearch-host:9200',
            log: 'trace'
        });
    };
    isAvailable(): PromiseLike<String> {
        return this._client.ping({
            requestTimeout: Infinity
        });
    }
}

This seems to work fine. Logging shows me that requests are answered correctly.

Here's my component:

import { OnInit, Component } from '@angular/core';
import { ElasticsearchService } from './services/elasticsearch.service';

@Component({
    selector: 'foo',
    templateUrl: './foo.component.html',
    providers: [ElasticsearchService]
})
export class TimeLineComponent implements OnInit {

    private status: String = 'not ok';
    constructor(private esService: ElasticsearchService) { } ;

    ngOnInit(): void {
        this.showStatus();
    }

    showStatus(): void {
        this.esService.isAvailable()
            .then( response => this.status = 'OK' );
    }

}

and here's the template:

status:{{status}}

I don't understand why my browser keeps showing "not ok". What am I missing here?

Ijon Tichy
  • 61
  • 9

1 Answers1

3

I think the reason the view is not refreshing is that the elasticsearch client uses its own deferred/promise implementation which is not picked up by Zone.js.

I found two possible solutions:

1: Run change detection manually after you set the component variable

2: Replace the default defer method in the client. Luckily it's easy enough (I stole the idea from elasticsearch.jquery.js)

function defer() {
  let resolve, reject, promise;

  promise = new Promise((_resolve, _reject) => {
    resolve = _resolve;
    reject = _reject;
  });

  return { resolve, reject, promise };
}

this.client = new Client({
  host: 'http://my-elasticsearch-host:9200',
  log: 'trace',
  defer: defer
});

Because this is using the standard Promise class, it is picked up by Zone correctly.

I'm still testing whether this minimalistic replacement for defer() is enough, but it could be that it needs additional methods. I'll post an update if something comes up.

Community
  • 1
  • 1