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?

4
  • did you add ElasticsearchService in the providers array somewhere? Commented Mar 5, 2017 at 14:11
  • It's in my app.module.ts and I've tried adding "providers: [ElasticsearchService]" to my component (See edit) Still no luck :( Commented Mar 5, 2017 at 17:24
  • Is your request actually being issued? Is there a response to the request, or is there an error? Commented Mar 6, 2017 at 5:16
  • yes the request is being issued. Elasticsearch responds correctly. I can even log the results from within the "then" method. It just doesn't update the {{status}}. Commented Mar 6, 2017 at 11:31

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.