ionic-framework: bug(infinite-scroll): throws uncatchable error if scrollToTop is called before it is resolved

Ionic version: (check one with “x”) [ ] 1.x (For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1) [ ] 2.x [x] 3.x

I’m submitting a … (check one with “x”) [x] bug report [ ] feature request [ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/

Current behavior: Having infinite scroll, calling content.scrollToTop() before last content.scrollToTop() resolves, throws an un-catchable error, and breaks the app.

ERROR TypeError: Cannot read property ‘timeStamp’ of null at InfiniteScroll._onScroll (infinite-scroll.ts:233) at SafeSubscriber.schedulerFn [as _next] (event_emitter.ts:121) at SafeSubscriber.__tryOrUnsub (Subscriber.ts:254) at SafeSubscriber.next (Subscriber.ts:204) at Subscriber._next (Subscriber.ts:135) at Subscriber.next (Subscriber.ts:95) at EventEmitterProxy.Subject.next (Subject.ts:61) at EventEmitterProxy.EventEmitter.emit (event_emitter.ts:80) at ScrollView.scroll.onScroll (content.ts:437) at ScrollView.setScrolling (scroll-view.ts:74)

Expected behavior: Either be able to catch the error, or better yet don’t error.

Steps to reproduce: Plunker: http://plnkr.co/edit/ptdHfTMhBxwvAOOUvizQ?p=preview Steps:

  • Scroll to 500 or so
  • Tap scrollToTop twice fast
  • Look at console. If no error, try again.

You can do it only once though (per refresh), because it kills the thread.

Ionic info: (run ionic info from a terminal/cmd prompt and paste output below):

global packages:

    @ionic/cli-utils : 1.4.0
    Ionic CLI        : 3.4.0

local packages:

    @ionic/app-scripts              : 2.0.0
    @ionic/cli-plugin-ionic-angular : 1.3.1
    Ionic Framework                 : ionic-angular 3.5.0

System:

    Node       : v8.1.2
    OS         : Windows 10
    Xcode      : not installed
    ios-deploy : not installed
    ios-sim    : not installed
    npm        : 5.0.3 

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 20
  • Comments: 33 (6 by maintainers)

Most upvoted comments

Hi @youssmak, open file ../project/node_modules/ionic-angular/components/infinite-scroll/infinite-scroll.js then replace this code

        if (this._lastCheck + 32 > ev.timeStamp) {
            // no need to check less than every XXms
            return 2;
        }
        this._lastCheck = ev.timeStamp;

with this

        try {
            if (this._lastCheck + 32 > ev.timeStamp) {
                // no need to check less than every XXms
                return 2;
            }
            this._lastCheck = ev.timeStamp;
        } catch (e) {
            // ev is undefined
            return 2;
        }

Note: you have to start app again ionic serve, ionic-app-script wont build on node_modules changes

I don’t think this will get fixed soon, as the holidays are here and the team is focused on getting Ionic v4 ready.

I have temporarily switched to jQuery for scroll top until this is fixed. Here’s my code

// scroll top class
import { Content, Platform } from 'ionic-angular';
import { throttle } from 'lodash';
import * as $ from 'jquery';

export class ScrollTopHandler {
  private scrolling: boolean = false;
  private scrollEl: JQuery;

  constructor(private content: Content, private platform: Platform) {
    // optional, to prevent scroll top triggered too many times
    this.scrollTop = throttle(this.scrollTop, 500, { leading: true, trailing: false });
  }

  scrollTop() {
    if (!this.scrollEl) {
      this.scrollEl = $(this.content.getScrollElement());
    }

    // scroll top in progress
    if (this.scrolling) {
      return;
    }

    // page has not been scrolled down
    if (this.scrollEl.scrollTop() === 0) {
      return;
    }

    this.scrolling = true;

    // need to stop scroll momentum on ios before scroll top
    if (this.platform.is('ios')) {
      // disable and stop scroll momentum
      this.scrollEl.css('-webkit-overflow-scrolling', 'auto');
      this.scrollEl.css('overflow', 'hidden');

      setTimeout(() => {
        // re-enable scroll momentum
        this.scrollEl.css('-webkit-overflow-scrolling', 'touch');
        this.scrollEl.css('overflow', '');

        this.triggerScrollTop();

      }, 50);

    } else {
      this.triggerScrollTop();
    }
  }

  private triggerScrollTop() {
    this.scrollEl.animate({ scrollTop: 0 }, 300, () => { this.scrolling = false; });

    // use this method may trigger ev.timeStamps error...
    // this.content
    //   .scrollToTop(300)
    //   .then(() => {
    //     this.scrolling = false;
    //   });
  }
}
// example usage
import { Component, ViewChild, OnInit } from '@angular/core';
import { IonicPage, Platform } from 'ionic-angular';
import { ScrollTopHandler } from './scrollTopHandler';

@IonicPage({ name: 'home' })
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage implements OnInit {
  @ViewChild(Content) content: Content;

  constructor(private platform: Platform) { }

  ngOnInit() {
    this.scrollTopHandler = new ScrollTopHandler(this.content, this.platform);
  }

  triggerScrollTop() {
    this.scrollTopHandler.scrollTop();
  }
}

@jordins Not that I know of. This might not be a problem in v4

thks @sfaizanh but it’s a bad habit to edit node_modules files directly. The next time you will update your dependencies you will lost all of your changes. You could do it only if you want to test some changes and you don’t have the time to fork the repo.

annoying issue 😕

here is my temporary fix (works partially : only if scrollToTop is tapped multiple times and not if content is scrolling)

scrollToTop(): void {
    if (!this.scrollingTop) {
      this.scrollingTop = true;
      try {
        this.ionContent.scrollToTop()
          .then(res => this.scrollingTop = false)
          .catch(err => this.logService.warn(err)); // show log in dev env
      } catch (e) {
        this.scrollingTop = false
        this.logService.warn(e); // show log in dev env
      }
    }
  }

Thank you so much for sharing your workaround, @laitedliang. I just incorporated it into my code, and it is getting me around the issue for now.

The workaround works like charm. Thank you @sfaizanh

@AmitMY could you please merge the PR #13719 ?

Updated the Plunkr to demonstrate that even when surrounding this.content.scrollToTop with try/catch, infinite scroll stops working after the error is thrown: http://plnkr.co/edit/DiLYnRvLM2q8TW5DN9dJ?p=preview.

To recreate: scroll down a way, then either click “scrollToTop()” while there is still scroll momentum, or just double click “scrollToTop()”. This will throw the error. Now, scroll to the bottom of list, and infinite scroll is not triggered.

I’ve verified that this is still occurring in Ionic 3.8.0.