0

I am busy writing a service to return data to a component in my angular app (ng4). The data is retrieved from a smart contract.

I seem to be getting the following error:

HomeComponent_Host.html:1 ERROR TypeError: this.smartContractService.getDrawId(...).subscribe is not a function

My component code:

    this.smartContractService.getDrawId().subscribe(data => {
        console.log('Result:: ', data);
    });

And my service method:

getDrawId(): Observable<any> {
    let gameObject;
    return this.Game
        .deployed()
        .then(instance => {
            gameObject = instance;
            return gameObject.getDrawId.call();
        })
        .then(value => {
            return value; //console.log(value) returns the data.
        })
        .catch(error => {
            console.error('Error getting draw id; see log.');
            console.log(error);
        });
}

I am not sure how to get the data back from the service and to the calling component...

4
  • 1
    There seems to be a mixup between promises and observables. Most of your code in getDrawId is written as though this.Game.deployed() is returning a promise (with .thens and .catches), but then you say the return type is an Observable<any> and try to use it as an observable. Commented Sep 20, 2017 at 12:24
  • Yeah, promises and observables are my Achilles heel. Confuse the crap out of me. Commented Sep 20, 2017 at 12:26
  • 1
    @HappyCoder, Observables are a lot like Promises but whereas Promises are a one-and-done (ie, you make an HTTP request, it returns a response), Observables are continuous...at its most basic it's a lot like a publish-subscribe, something keeps pumping out values, which get pushed into a first-in-first-out queue. And when there's 1 or more subscribers it starts pushing those values out to the subscriber(s). Again, this is the most basic example. Commented Sep 20, 2017 at 12:34
  • gonZofish - good explanation. thank you! Commented Sep 20, 2017 at 12:43

1 Answer 1

2

You seem to be trying to combine promises and observables. Promises and observables have a bit of similarity, since they're both intended to deal with asynchronous things. But while promises only ever deal with 1 eventual value, Observables deal with a stream of 0, 1, or many values.

Apparently, this.Game.deployed() is returning a promise, because you're calling .then on it (which is the way you interact with promises). However, getDrawId claims to return an Observable<any>, and you're calling .subscribe; a function that only exists on observables, not promises.

So the path forward depends on what your intent is. Since this.game.deployed returns a promise, perhaps you want to use promises throughout, in which case you can do this:

getDrawId(): Promise<any> { //<--- type changed
    let gameObject;
    return this.Game
        .deployed()
        .then(instance => {
            gameObject = instance;
            return gameObject.getDrawId.call();
        })
        .then(value => {
            return value; //console.log(value) returns the data.
        })
        .catch(error => {
            console.error('Error getting draw id; see log.');
            console.log(error);
        });
}

// And use it with .then instead of .subscribe
this.smartContractService.getDrawId().then(data => {
    console.log('Result:: ', data);
});

Alternatively, maybe you want getDrawId to return an observable, in which case you could either do a larger refactor in which you make this.Game.deployed() use observables so that you're using them throughout; or you could leave that as is and create an observable around the promise:

getDrawId(): Observable<any> {
    let gameObject;
    return Observable.fromPromise(this.Game
        .deployed()
        .then(instance => {
            gameObject = instance;
            return gameObject.getDrawId.call();
        })
        .then(value => {
            return value; //console.log(value) returns the data.
        })
        .catch(error => {
            console.error('Error getting draw id; see log.');
            console.log(error);
        });
    );
}

Also, while I left in the <any>s from your code, i'd recommend making a more specific type if you know it.

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

1 Comment

Thank you for the detailed response. I will get these right some day!

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.