简体   繁体   中英

Cannot trigger next function when previous completed

I'm trying to make a chain reaction by executing next function after executing previous one. Code looks like this:

var med = {

    imgLoadTime : 2000,

    easingEffect : 'easeOutQuart',

    scrollEase : 'easeInOutQuad',

    effectDuration : 1000,

    currentPage : '',

    runAnimations : function(){
                        if(this.currentPage == '#slide5'){
                            this.initAssets();
                        }
                    },

    initAssets : function(){
                    $('#asset-1').animate(
                        {left : '50%'}, 
                        { 
                            duration: this.effectDuration, 
                            easing: this.easingEffect, 
                            complete: this.assetTwo 
                        });
                },

    assetTwo : function(){
                    console.log('two');
                    debugger;
                    $('#asset-2').animate(
                        {left : '50%'}, 
                        { 
                            duration: this.effectDuration, 
                            easing: this.easingEffect, 
                            complete: this.assetThree 
                        });
                },

    assetThree : function(){
                    console.log('three');
                    $('#asset-3').animate(
                        {left : '50%'}, 
                        {
                            duration: this.effectDuration, 
                            easing: this.easingEffect, 
                            complete: console.log('weszlo')
                        });
                }

};  

This is how my object looks like. Then I run function runAnimations as a property of object. What is weird that during this chain only assetTwo function executes, but no further (assetThree). Why so?

You can't do this type of definition:

complete: this.assetTwo 

It will call assetTwo, but it won't have the right this value. Instead, you need to do this:

           initAssets : function(){
                var self = this;
                $('#asset-1').animate(
                    {left : '50%'}, 
                    { 
                        duration: this.effectDuration, 
                        easing: this.easingEffect, 
                        complete: function() {self.assetTwo()}
                    });
            },

Same for the other complete functions. You need to save the value of this into a local variable and then use it in the complete function to invoke the next method. This will make sure that this is set properly for the next method.

Your this changes with each function, you could reference it by med instead to get the desired result:

assetTwo : function(){

                //debugger;
                $('#asset-2').animate(
                    {left : '50%'}, 
                    { 
                        duration: med.effectDuration, 
                        easing: med.easingEffect, 
                        complete: med.assetThree 
                    });
            },

Updated fiddle: http://jsfiddle.net/johnkoer/2KHnc/16/

在你的javascript代码中的所有地方使用med而不是this

For nice tight code use a jQuery $.Deferred.pipe() chain as described here

You should end up with something like this :

var med = {
    imgLoadTime: 2000,
    currentPage: '',
    css : {left: '50%'},
    animOptions: {
        duration: 1000, 
        easing: 'easeOutQuart'
    };
    runAnimations: function() {
        if(med.currentPage == '#slide5') {
            $.Deferred(function(dfr) {
                dfr.pipe(function() {
                    return $('#asset-1').animate( med.css, med.animOptions );
                }).pipe(function() {
                    return $('#asset-2').animate( med.css, med.animOptions );
                }).pipe(function() {
                    return $('#asset-3').animate( med.css, med.animOptions );
                })
            }).resolve();
        }
    }
};

untested

Get the hang of Deferreds and you'll never look back.

Unless the med object is important for other reasons, then it would be simpler just to have runAnimations() rather than an object wrapper :

function runAnimations() {
    var imgLoadTime = 2000,
    currentPage = '',
    css = {left: '50%'},
    animOptions = {
        duration: 1000, 
        easing: 'easeOutQuart'
    };
    if(currentPage == '#slide5') {
            $.Deferred(function(dfr) {
                dfr.pipe(function() {
                    return $('#asset-1').animate( css, animOptions );
                }).pipe(function() {
                    return $('#asset-2').animate( css, animOptions );
                }).pipe(function() {
                    return $('#asset-3').animate( css, animOptions );
                })
            }).resolve();
    }
}

This way references to the fixed parameters are straightforward.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM