Ionic-framework: Swiper breaking if accessed quickly enough and multiple times

Created on 1 Feb 2017  路  17Comments  路  Source: ionic-team/ionic-framework

Ionic version:
[x ] 2.x

I'm submitting a ...
[x ] bug report

Current behavior:
If we navigate quickly between pages that have a swiper in some cases the ngOnDestroy of the swiper breaks

Expected behavior:
The swiper need to initialize every time it's called

Steps to reproduce:
Create 2 pages in a tabbed interface and add to the first a swiper.
Try to navigate between those pages a lot of times stressing as much the swiper component

Related code:
When trying to destroy the component here:
https://github.com/driftyco/ionic/blob/master/src/components/slides/slides.ts#L1092
this is not defined.
This might be occuring cause of this:
https://github.com/driftyco/ionic/blob/master/src/components/slides/slides.ts#L939

  ngAfterContentInit() {
    this._plt.timeout(() => {
      this._initSlides();
    }, 300);
  }

timing out or this:
https://github.com/driftyco/ionic/blob/master/src/components/slides/slides.ts#L903

    if (viewCtrl) {
      var subscription = viewCtrl.readReady.subscribe(() => {
        subscription.unsubscribe();
        this._initSlides();
      });
    }

not managing to resolve the subscription before the destroy of the component.

As all above are asynchronous the ngOnDestroy might be called before the initialization of the component and as a consequence breaking it.

Potential fix would be to add a check for the this if it's present before trying to access it.

ngOnDestroy() {
    if(!this) {
      return;
    }
    this._init = false;

    this._unregs.forEach(unReg => {
      unReg();
    });
    this._unregs.length = 0;

    destroySwiper(this);

    this.enableKeyboardControl(false);
  }

Most helpful comment

This issue still exists

All 17 comments

Thanks, we will take a look into this.

i made a PR for this, issue
https://github.com/driftyco/ionic/pull/11100

Is this issue fixed? Is there any workaround for now to solve this?

@deepak07 look the PR #11100 to include the fix on your app

I think the issue still exists, I am seeing ERROR TypeError: Cannot read property 'hasAttribute' of undefined error even with latest release.

can you past your ionic info

This issue still exists

This issue still exists
global packages:

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

local packages:

@ionic/app-scripts              : 1.3.12
@ionic/cli-plugin-cordova       : 1.4.0
@ionic/cli-plugin-ionic-angular : 1.3.1
Cordova Platforms               : ios 4.4.0
Ionic Framework                 : ionic-angular 3.5.0

System:

Node       : v6.11.0
OS         : macOS Sierra
Xcode      : Xcode 8.3 Build version 8E162 
ios-deploy : 1.9.1 
ios-sim    : 6.0.0 
npm        : 3.10.10

Why is closed this? I'm still getting error calling SlideTo:

ionViewDidLoad() {

    this.localSettings.load().then(() => this.localSettings.getValue(this.localSettings.SETTINGS_INTRO_SEEN).then(res => {

      if (res) {
        this.slides.slideTo(5);        
      }
    })); 
  }

+1 . I still got the same error when init the slides in ionViewDidLoad()

Error: Uncaught (in promise): TypeError: Cannot read property 'length' of undefined
TypeError: Cannot read property 'length' of undefined
    at destroyLoop (http://localhost:8100/build/vendor.js:53273:51)
    at destroySwiper (http://localhost:8100/build/vendor.js:53539:9)
    at Slides.ngOnDestroy (http://localhost:8100/build/vendor.js:61948:86)
    at callProviderLifecycles (http://localhost:8100/build/vendor.js:11675:18)
    at callElementProvidersLifecycles (http://localhost:8100/build/vendor.js:11644:13)
    at callLifecycleHooksChildrenFirst (http://localhost:8100/build/vendor.js:11628:17)
    at destroyView (http://localhost:8100/build/vendor.js:12889:5)
    at callViewAction (http://localhost:8100/build/vendor.js:13035:13)
    at execEmbeddedViewsAction (http://localhost:8100/build/vendor.js:12973:17)
    at destroyView (http://localhost:8100/build/vendor.js:12887:5)
    at c (http://localhost:8100/build/polyfills.js:3:13535)
    at Object.reject (http://localhost:8100/build/polyfills.js:3:12891)
    at NavControllerBase._fireError (http://localhost:8100/build/vendor.js:50928:16)
    at NavControllerBase._failed (http://localhost:8100/build/vendor.js:50916:14)
    at http://localhost:8100/build/vendor.js:50971:59
    at t.invoke (http://localhost:8100/build/polyfills.js:3:9283)
    at Object.onInvoke (http://localhost:8100/build/vendor.js:4657:37)
    at t.invoke (http://localhost:8100/build/polyfills.js:3:9223)
    at r.run (http://localhost:8100/build/polyfills.js:3:4452)
    at http://localhost:8100/build/polyfills.js:3:14076

+1, Until fixing this issue, can I rely on a timeout of 100 ms and move on ??

@mickadoua : Your code is already there in my files. Still I'm getting this issue.
untitled

Just adding <ion-slides></ion-slides> in my html brakes the code for that particular page. I get an runtime error ERROR Error: Uncaught (in promise): TypeError: Cannot read property '__zone_symbol__setTimeout' of undefined.

cli packages:

    @ionic/cli-plugin-cordova       : 1.6.1
    @ionic/cli-plugin-ionic-angular : 1.4.1
    @ionic/cli-utils                : 1.7.0
    ionic (Ionic CLI)               : 3.7.0

global packages:

    Cordova CLI : 7.0.1

local packages:

    @ionic/app-scripts : 1.3.6
    Cordova Platforms  : ios 4.4.0
    Ionic Framework    : ionic-angular 3.4.2

System:

    Node : v7.9.0
    OS   : macOS Sierra
    npm  : 4.2.0

why its closed????
As everyone says. This problem is still existing.

I have one solution for that, but is a bad way for sure:

ngAfterViewInit(){
    setTimeout(() => {
      this.slides.slideTo(2);
    }, 50);
}

Hello from 2018. This issue is still exist and setTimeout is bad solution. For devices with powerful hardware 50ms is quite enough, but for old devices sometimes even 500ms is not enough and error appears.

This is not cordova or some third party module issue, this is bug in your framework core. Please fix it or add status won't fix and add in docs mark not production ready to slides feature.

Update: dirty solution that work in all cases is to wrap logic in try/catch

    private _recursiveSlideTo(slideIndex: number): Promise<void> {
        return new Promise((resolve: Function, reject: Function): void => {
            let tryCount: number = 0;
            this._slideTo(slideIndex, tryCount, resolve, reject);
        });
    }

    private _slideTo(slideIndex: number, tryCount: number, resolve: Function, reject: Function): void {
        try {
            this._slides.slideTo(slideIndex, 0);
            resolve();
        } catch (error) {
            if (tryCount < 100) {
                tryCount++;
                setTimeout(() => this._slideTo(slideIndex, tryCount, resolve, reject), 50);
            } else {
                reject(error);
            }
        }
    }

and call this._recursiveSlideTo(1) that return promise on finish and can be chain with other logic.

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GeorgeAnanthSoosai picture GeorgeAnanthSoosai  路  3Comments

giammaleoni picture giammaleoni  路  3Comments

masimplo picture masimplo  路  3Comments

SebastianGiro picture SebastianGiro  路  3Comments

danbucholtz picture danbucholtz  路  3Comments