11

Hi I am trying to get an example of a countdown timer I found searching on Stack found here: Time CountDown in angular 2

This is my code:

import { Component, ElementRef, OnInit, OnDestroy } from '@angular/core';
import { Observable, Subscription, interval  } from 'rxjs';

@Component({
  selector: 'app-timer',
  templateUrl: './timer.component.html',
  styleUrls: ['./timer.component.css']
})
export class TimerComponent implements OnInit {
  private future: Date;
  private futureString: string;
  private diff: number;
  private $counter: Observable<number>;
  private subscription: Subscription;
  private message: string;

  constructor(elm: ElementRef) {
      this.futureString = elm.nativeElement.getAttribute('inputDate');
  }

  dhms(t) {
      let days, hours, minutes, seconds;
      days = Math.floor(t / 86400);
      t -= days * 86400;
      hours = Math.floor(t / 3600) % 24;
      t -= hours * 3600;
      minutes = Math.floor(t / 60) % 60;
      t -= minutes * 60;
      seconds = t % 60;

      return [
          days + 'd',
          hours + 'h',
          minutes + 'm',
          seconds + 's'
      ].join(' ');
  }

  ngOnInit() {
      this.future = new Date(this.futureString);
      this.$counter = Observable.interval(1000).map((x) => {
          this.diff = Math.floor((this.future.getTime() - new Date().getTime()) / 1000);
          return x;
      });

      this.subscription = this.$counter
          .subscribe((x) => this.message = this.dhms(this.diff));
  }
}

Getting the following error:

timer/timer.component.ts(44,34): error TS2339: Property 'interval' does not exist on type 'typeof Observable'.

I have tried every measure of importing I could find on Google but nothing has worked. I also updated to the latest version of rxjs and still nothing. Any help would be greatly appreciated.

I believe I may have some kind of versioning issue or something. Really stumped.

npm ERR! peer dep missing: jquery@1.9.1 - 3, required by bootstrap@4.1.1
npm ERR! peer dep missing: popper.js@^1.14.3, required by bootstrap@4.1.1
npm ERR! missing: mkdirp@0.5.1, required by node-pre-gyp@0.9.1
npm ERR! missing: minimist@0.0.8, required by mkdirp@0.5.1
npm ERR! missing: minimatch@3.0.4, required by ignore-walk@3.0.1
npm ERR! missing: brace-expansion@1.1.11, required by minimatch@3.0.4
npm ERR! missing: balanced-match@1.0.0, required by brace-expansion@1.1.11
npm ERR! missing: concat-map@0.0.1, required by brace-expansion@1.1.11
npm ERR! missing: console-control-strings@1.1.0, required by npmlog@4.1.2
npm ERR! missing: inherits@2.0.3, required by readable-stream@2.3.6
npm ERR! missing: safe-buffer@5.1.1, required by readable-stream@2.3.6
npm ERR! missing: safe-buffer@5.1.1, required by string_decoder@1.1.1
npm ERR! missing: console-control-strings@1.1.0, required by gauge@2.7.4
npm ERR! missing: string-width@1.0.2, required by gauge@2.7.4
npm ERR! missing: strip-ansi@3.0.1, required by gauge@2.7.4
npm ERR! missing: code-point-at@1.1.0, required by string-width@1.0.2
npm ERR! missing: is-fullwidth-code-point@1.0.0, required by string-width@1.0.2
npm ERR! missing: strip-ansi@3.0.1, required by string-width@1.0.2
npm ERR! missing: number-is-nan@1.0.1, required by is-fullwidth-code-point@1.0.0
npm ERR! missing: ansi-regex@2.1.1, required by strip-ansi@3.0.1
npm ERR! missing: string-width@1.0.2, required by wide-align@1.1.2
npm ERR! missing: inherits@2.0.3, required by glob@7.1.2
npm ERR! missing: minimatch@3.0.4, required by glob@7.1.2
npm ERR! missing: once@1.4.0, required by glob@7.1.2
npm ERR! missing: once@1.4.0, required by inflight@1.0.6
npm ERR! missing: wrappy@1.0.2, required by inflight@1.0.6
npm ERR! missing: wrappy@1.0.2, required by once@1.4.0
npm ERR! missing: minipass@2.2.4, required by tar@4.4.1
npm ERR! missing: mkdirp@0.5.1, required by tar@4.4.1
npm ERR! missing: safe-buffer@5.1.1, required by tar@4.4.1
npm ERR! missing: yallist@3.0.2, required by tar@4.4.1
npm ERR! missing: minipass@2.2.4, required by fs-minipass@1.2.5
npm ERR! missing: safe-buffer@5.1.1, required by minipass@2.2.4
npm ERR! missing: yallist@3.0.2, required by minipass@2.2.4
npm ERR! missing: minipass@2.2.4, required by minizlib@1.1.0
kian
  • 1,449
  • 2
  • 13
  • 21
user68288
  • 702
  • 2
  • 6
  • 27
  • In the example they seem to be importing form `from 'rxjs/Rx';` and your importing from `rxjs` – BeeBee8 May 20 '18 at 17:04
  • Possible duplicate of [Property interval does not exist in the type observable](https://stackoverflow.com/questions/49572854/property-interval-does-not-exist-in-the-type-observable). Try to search on the error you're getting; there are usually a lot of hits to try. – Heretic Monkey May 20 '18 at 17:04
  • Hi Mike -- I actually search all over and came across that same page. Still results in errors. error TS2307: Cannot find module 'rxjs-compat/observable/interval'. node_modules/rxjs/observable/interval"' has no exported member 'interval'. – user68288 May 20 '18 at 17:08
  • Note that the convention with variables of type `Observable` is to suffix them with `$`, not prefix them. You can also choose not to add a suffix. – David Walschots May 20 '18 at 18:06
  • I have to say your usage of `map` in uncommon. Is there a reason to use it instead of just immediately subscribing and doing your operations there? You're not mapping the stream's value to something different... – David Walschots May 20 '18 at 18:29
  • I am honestly really unsure of what I am doing. I am just trying to get to a point where I can have a clock down timer display on my HTML page that is based on a variable date/time that I set. If there is a better way please let me know. I am just going based on things I found on Stack. – user68288 May 20 '18 at 18:42

2 Answers2

16

Simply write:

import { interval } from 'rxjs';
import { map } from 'rxjs/operators'

interval(1000).pipe(
  map((x) => { /* your code here */ })
);

In RxJS 6+ there's no Observable.interval function.

gonzo
  • 2,103
  • 1
  • 15
  • 27
David Walschots
  • 12,279
  • 5
  • 36
  • 59
  • Hi -- when trying this I received the following error: error TS2339: Property 'map' does not exist on type 'Observable'. Thanks for the help, newbie here. – user68288 May 20 '18 at 18:26
  • My bad. I've updated the code to reflect correct usage in RxJS 6+. – David Walschots May 20 '18 at 18:28
  • The code compiles and I get a result but it isn't functioning at all how I expected. It returns a date of -17000+ days. I am honestly really unsure of what I am doing. I am just trying to get to a point where I can have a clock down timer display on my HTML page that is based on a variable date/time that I set. If there is a better way please let me know. I am just going based on things I found on Stack. Also since you resolved the issue I created this for I will mark yours as answer. – user68288 May 20 '18 at 19:03
  • OK. Sounds to me like your question is answered. I'd suggest debugging your code to see where exactly your resulting date is calculated. Just step through it and I'm sure you'll find it. If you have any further questions later you can open a new question. – David Walschots May 20 '18 at 19:10
2

From Rxjs 6.0 you have to import interval from rxjs/observable/interval.

And you have to use pipe operator to execute infinite number of operator sequentially.

import { interval } from 'rxjs';
import { map } from 'rxjs/operators'

this.$counter = interval(1000).pipe(
   map((x) => {
      this.diff = Math.floor((this.future.getTime() - new Date().getTime()) / 1000);
      return x;
  });
)


Reference: https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md#build-your-own-operators-easily

Ritwick Dey
  • 18,464
  • 3
  • 24
  • 37
  • I am now receiving this error: ERROR in ./src/app/hertz/timer/timer.component.ts Module not found: Error: Can't resolve 'rxjs/observable/interval' in 'C:\Users\USER\GitHub\angular\src\app\hertz\timer' Thank you for helping. Code in my ngOnInIt: ngOnInit() { this.future = new Date(this.futureString); interval(1000).pipe( map((x) => { this.diff = Math.floor((this.future.getTime() - new Date().getTime()) / 1000); return x; }); ) – user68288 May 20 '18 at 17:58
  • What is the `rxjs` version. Check in the `package.json` – Ritwick Dey May 20 '18 at 18:00
  • make sure `rxjs 6.0+` install properly – Ritwick Dey May 20 '18 at 18:03
  • In my package.json it displays: "rxjs": "^6.1.0", – user68288 May 20 '18 at 18:04
  • Just for debugging purpose. run `npm ls`... do you getting any error that package is missing ? – Ritwick Dey May 20 '18 at 18:06
  • When running npm ls I have 35 pacakges missing I listed in the original post now. I am very new to Angular so I am unsure of how bad this is.... – user68288 May 20 '18 at 18:11
  • Opps! try `npm install` first. – Ritwick Dey May 20 '18 at 18:14
  • Importing `interval` from `rxjs/observable/interval` only exists in RxJS 6 for backward compatibility reasons. It also requires installing the `rxjs-compat` package, but is not recommended. – David Walschots May 20 '18 at 18:20
  • Nope. You're probably wrong! Official docs says `rxjs/operators will likely make your application bundle larger`. And `rxjs/observable/interval` is recommended. Check the last section of reference of the answer. @DavidWalschots – Ritwick Dey May 20 '18 at 18:31
  • Nope. You're probably wrong! Official docs says `rxjs/operators will likely make your application bundle larger`. And `rxjs/observable/interval` is recommended. Check the last section of reference of the answer. @DavidWalschots – Ritwick Dey May 20 '18 at 18:31
  • @RitwickDey the documentation you're referring to is for RxJS 5.5, not 6+. – David Walschots May 20 '18 at 18:32
  • Oh My God! Seriously ? Now check https://github.com/ReactiveX/rxjs/blob/6.1.0/doc/pipeable-operators.md ......... Anyway, that was not `5.5 docs`. That was latest link. `import { map } from 'rxjs/operators/map';` is also recommended. @DavidWalschots – Ritwick Dey May 20 '18 at 18:36
  • Going to a tagged version within Git doesn't mean the documentation is for that version. It simply means the file was tagged with that name. The file you're referring to was last updated 6 weeks before the RxJS 6.0 release. In any case, importing `interval` from `rxjs/observable/interval` does not work. – David Walschots May 20 '18 at 18:38
  • okay. May be I'm wrong. Show me a docs where they talk about bundling. – Ritwick Dey May 20 '18 at 18:40
  • I'm not sure what docs to show you... RxJS 6+ is fully tree-shakeable if that is what you're asking. – David Walschots May 20 '18 at 18:53
  • 1
    @RitwickDey have you found the documentation you need to understand that the import in your answer is incorrect for RxJS 6? If not, be sure to read the [migration documentation](https://github.com/ReactiveX/rxjs/blob/master/MIGRATION.md). – David Walschots May 22 '18 at 13:57
  • return this.diff instead of x – VIKAS KOHLI Nov 19 '19 at 10:00