6

I have the following subscribe function for some service.

this.sub = this.route.params.subscribe(params => {
this.id = params['id'];
this._someService
      .thisById(this.id)
      .subscribe(value => {
         this.valueObj = value; 
     });
});

This seems all right. Except that I need to use the this.valueObj in the following functions outside the subscribe function.

private  _checkOpeningHours(data: any): string {
    const curDayName = this._getDayName();
    const todaysOpeningData = ***this.valueObj***.openHours[curDayName];

    if (!todaysOpeningData) return "ERROR!";
    if (!todaysOpeningData.status) return `IT'S ${curDayName.toUpperCase()} - WE ARE CLOSED TODAY!`;

    return `IT'S ${curDayName.toUpperCase()}, ${new Date().toLocaleString("en-US", { hour: '2-digit', minute: '2-digit' })} - ${this._isOpen(todaysOpeningData) ? 'WE ARE OPEN' : 'SORRY, WE ARE CLOSED'}!`;

  }

  private _refresh() {
    this.opening = this._checkOpeningHours(***this.valueObj***.openHours[this._getDayName()]);

    setTimeout(() => this._refresh(), 60 * 1000);
  }

How can I get these functions to work with the this.valueObj?

LearnToday
  • 2,762
  • 9
  • 38
  • 67
  • I don't know much about angular but I remember that it uses a lot of dependency injection. Can you add a parameter with matching name to the method so that angular injects the value? – styfle Dec 22 '16 at 15:05
  • are you sure that it's not an issue with the thisById function being asynchronous and that you are calling the other function before thisById returns? – toskv Dec 22 '16 at 15:08
  • where are the `_checkOpeningHours` and `_refresh` functions defined? it's not in the same class as the other code? pls add some more context – lenny Dec 22 '16 at 15:10
  • @toskv thisById() function is async which is what it is suppose to be. – LearnToday Dec 22 '16 at 15:10
  • @lenny In the same class, but as I know subscribe() functions won't let their variable values to be use outside the subscribe() function. – LearnToday Dec 22 '16 at 15:12
  • then how are the 2 being called? what's the time relation between the 2 of them? :) – toskv Dec 22 '16 at 15:13
  • you are using `this` to access **valueObj**, so I assume that it's a class member. you should be able to use it like you already do in your functions. Did you try it? What is the error? – lenny Dec 22 '16 at 15:16
  • @ObasiObenyOj he seems to be saving the result as a class property. There's no problem using that later from anywhere in the class, if the value is initialized. – toskv Dec 22 '16 at 15:16
  • @toskv this._refresh() is called in the ngOnInit(). And this_refresh() can be called inside the subscribe function which it will all work find. But the _checkOpeningHours() will still need the this.valueObj to get {{opening}} – LearnToday Dec 22 '16 at 15:17
  • @lenny I tried it, but this.valueObj outside the subscribe() function can't be used. – LearnToday Dec 22 '16 at 15:19

1 Answers1

6

Async calls need to be properly chained.

If you return an observable (requires map instead of subscribe)

someMethod() {
  this.sub = this.route.params.subscribe(params => {
  this.id = params['id'];
  return this._someService
      .thisById(this.id)
      .map(value => {
         return this.valueObj = value; 
     });
  });
}

then you can use it like

private  _checkOpeningHours(data: any): string {
  this.someMethod().subscribe(val => {
    console.log(val); // here the value is available
  });
}

Without proper chaining it's very likely that _checkOpeningHours() accesses this.valueObj looong before the value becomes available.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • For some reason I get this TypeError: Cannot read property 'subscribe' of undefined – LearnToday Dec 22 '16 at 15:34
  • Did you add the `return` to `return this._someService`? – Günter Zöchbauer Dec 22 '16 at 15:35
  • I also forgot a `return` inside `map` (necessary because of `{}`) - fixed. – Günter Zöchbauer Dec 22 '16 at 15:36
  • I thought is the second `return` but when I add it I get the TypeError: this.someMethod(...).subscribe is not a function – LearnToday Dec 22 '16 at 15:38
  • I don't know how your code is organized because the context is missing in your question. My answer assumes that `someMethod` and `_checkOpeningHours` are inside the same class. – Günter Zöchbauer Dec 22 '16 at 15:40
  • You are right. All is in the same class.` Error:: in sublime ( property subscribe does not exist on type subscription`. Whatever that means. – LearnToday Dec 22 '16 at 15:44
  • I guess you have still `subscribe` instead of `map` in `someMethod`. – Günter Zöchbauer Dec 22 '16 at 15:46
  • `this.sub = this.route.params.subscribe(params => { this.id = params['id']; // Retrieve Pet with Id route param return this._placesService .findPetById(this.id) .map(value => { return value; }); });` that's my code. ***TypeError: Cannot read property 'subscribe' of undefined*** – LearnToday Dec 22 '16 at 15:47
  • Sorry, I misread your first lines of code because it's not properly indented. I think you should just call your `someMethod` from within `this.route.params.subscribe(...)` and be fine. – Günter Zöchbauer Dec 22 '16 at 15:50
  • Can you please edit your answer code so I get an understanding of what you mean. Thanks – LearnToday Dec 22 '16 at 15:53
  • It would be easier if you would first make more clear what you actually try to accomplish. Where do you have the first code block? Where is `_checkOpeningHours` being called from? – Günter Zöchbauer Dec 22 '16 at 15:55
  • From my question above, `_checkOpeningHours` is being called inside _refresh function. But `_checkOpeningHours` needs the `this.valueObj` to run. – LearnToday Dec 22 '16 at 15:58
  • Wouldn't it be enough to just use `setTimeout(() => this.valueObj ? this._refresh() : () => {}, 60 * 1000);`? to not execute `_refresh` when `valueObj` is not yet available? – Günter Zöchbauer Dec 22 '16 at 16:00
  • I can't figure away for that to be enough since I need to get opening time for today with current day name in the `_checkOpeningHours` . If there is a way for that I will go for it. – LearnToday Dec 22 '16 at 16:05
  • I see. Then just return `null` or something from `_checkOpeningHours` when `this.valueObj` is not yet available. – Günter Zöchbauer Dec 22 '16 at 16:07