javascript 函数完成时执行代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18641626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 12:43:35  来源:igfitidea点击:

Executing code when a function is complete

javascriptjquery

提问by alimac83

I have a function in my code that animates several elements. What I'm wanting to do is execute a sequence of code but only afterthis function has completed.

我的代码中有一个函数可以为多个元素设置动画。我想要做的是执行一系列代码,但只有在此功能完成后。

Say for example I had this:

比如说我有这个:

executeMyAnimationFunction();

// Execute this code AFTER executeMyAnimationFunction() has completed
alert('test');

So far I've tried using setTimeout but this doesn't seem to be very reliable. I've also tried using .promise() but this doesn't seem to execute properly either:

到目前为止,我已经尝试使用 setTimeout 但这似乎不是很可靠。我也试过使用 .promise() 但这似乎也不能正确执行:

$(executeMyAnimationFunction()).promise().done(function () {
    alert('test');
});

However I admit I be using it incorrectly. In the demoon the jquery site, it seems promise() is being used on the elements that are being animated. I tried doing it like this:

但是我承认我使用它不正确。在jquery 站点上的演示中,似乎对正在设置动画的元素使用了 promise()。我试着这样做:

$('#myAnimatedElement').promise().done(function () {
    alert('test');
});

and it seemedto work in certain scenarios but in others it didn't work. I wonder if this is a reliable way of using promise()?

似乎在某些情况下有效,但在其他情况下却不起作用。我想知道这是否是使用 promise() 的可靠方法?

Basically I'm stuck now with how I can do this. All I want to do is wait until a function has fully executed (the function simply animates a group of elements) and then continue with the execution of my code.

基本上我现在被困在如何做到这一点上。我想要做的就是等到一个函数完全执行(该函数只是为一组元素设置动画),然后继续执行我的代码。

Is there a simple way of doing this using jquery/javascript that I'm missing?

有没有一种简单的方法可以使用我缺少的 jquery/javascript 来做到这一点?

Thanks

谢谢

EDIT: To show my problem in a little more detail, here is the exact code I'm using:

编辑:为了更详细地显示我的问题,这是我正在使用的确切代码:

<script>
        $(function () {

            $(window).bind('hashchange', function (e) {
                if ($(':animated').length) {
                    return false;
                }

                var section = $.param.fragment();
                var current = $('#content').children(':visible').attr('id');

                $('a').removeClass('active');                

                // If this is the first load of the page, then animate in the initial content
                if (section === '') {                    
                    if (current === 'reception') {
                        animateContentIn("reception");                        
                    }
                    else {                        
                        $('a[href="#' + section + '"]').addClass('active');

                        // Animate out existing content
                        animateContentOut(current);

                        setTimeout(function () {
                            animateContentIn("reception");
                        }, 1000);
                    }
                }
                else {
                    // Otherwise find the current page content and animate out
                    animateContentOut(current);

                    setTimeout(function () {
                        animateContentIn(section);
                    }, 1000);
                }               
            })

            // Since the event is only triggered when the hash changes, we need to trigger
            // the event now, to handle the hash the page may have loaded with.
            $(window).trigger('hashchange');
        });       

        function animateContentIn(activePage) { 
            // Now animate in the new content
            switch (activePage) {
                case "floorspace":
                    animateFloorspaceElementsIn();
                    break;
                case "reception":
                    animateReceptionElementsIn();
                    break;
            }
        }

        function animateContentOut(currentPage) {
            // Now animate in the new content
            switch (currentPage) {
                case "floorspace":                    
                    animateFloorspaceElementsOut();
                    break;
                case "reception":
                    animateReceptionElementsOut();
                    break;
            }
        }

        function animateReceptionElementsIn() {
            $('#reception').show();

            $('#reception .title').animate({
                bottom: 520
            }, 400);

            $('#reception .tile1').animate({
                bottom: 504
            }, 600);

            $('#reception .tile2').animate({
                bottom: 504
            }, 700);

            $('#reception .hero').animate({
                bottom: 40
            }, 1000);

            $('#reception .content1').animate({
                bottom: 8
            }, 400);

            $('#reception .content2').animate({
                bottom: 8
            }, 500);
        }

        function animateReceptionElementsOut() {
            $('#reception .title').animate({
                bottom: -56
            }, 400);

            $('#reception .tile1').animate({
                bottom: -136
            }, 600);

            $('#reception .tile2').animate({
                bottom: -152
            }, 700);

            $('#reception .hero').animate({
                bottom: -464
            }, 1000, function () {
                $('#reception').hide();
            });

            $('#reception .content1').animate({
                bottom: -112
            }, 400);

            $('#reception .content2').animate({
                bottom: -104
            }, 500);
        }

        function animateFloorspaceElementsIn() {
            $('#floorspace').show();

            $('#floorspace .title').animate({
                bottom: 520
            }, 400);

            $('#floorspace .tile1').animate({
                bottom: 504
            }, 600);

            $('#floorspace .tile2').animate({
                bottom: 504
            }, 700);

            $('#floorspace .hero').animate({
                bottom: 40
            }, 1000);

            $('#floorspace .content1').animate({
                bottom: 8
            }, 400);

            $('#floorspace .content2').animate({
                bottom: 8
            }, 500);
        }

        function animateFloorspaceElementsOut() {
            $('#floorspace .title').animate({
                bottom: -56
            }, 400);

            $('#floorspace .tile1').animate({
                bottom: -136
            }, 600);

            $('#floorspace .tile2').animate({
                bottom: -152
            }, 700);

            $('#floorspace .hero').animate({
                bottom: -464
            }, 1000, function () {
                $('#floorspace').hide();
            });

            $('#floorspace .content1').animate({
                bottom: -112
            }, 400);

            $('#floorspace .content2').animate({
                bottom: -104
            }, 500);
        }
    </script>
</head>
<body>
    <div id="vert-wrapper">
        <div id="wrapper">
            <aside id="sidebar">
                <nav id="navigation">
                    <ul>
                        <li><a href="#">Building</a></li>
                        <li><a href="#reception">Reception</a></li>
                        <li><a href="#floorspace">Floor Space</a></li>
                        <li><a href="#">Views</a></li>
                        <li><a href="#">Terraces</a></li>
                        <li><a href="#">Profile</a></li>
                    </ul>
                    <ul>
                        <li><a href="#">Specification</a></li>
                        <li><a href="#">Plans</a></li>
                        <li><a href="#">Location</a></li>
                        <li><a href="#">Ten Storeys</a></li>
                        <li><a href="#">Gallery</a></li>
                        <li><a href="#">Contact</a></li>
                    </ul>
                </nav>
            </aside>  
            <div id="content">
                <article id="reception">
                    <h1 class="title">
                        <img src="/images/reception/title.png" alt="Edge" />
                    </h1>
                    <img src="/images/reception/1.jpg" alt="" class="tile1" />
                    <img src="/images/reception/2.jpg" alt="" class="tile2" />
                    <img src="/images/reception/hero.jpg" alt="" class="hero" />
                    <img src="/images/reception/content1.jpg" alt="" class="content1" />
                    <img src="/images/reception/content2.jpg" alt="" class="content2" />
                </article>
                <article id="floorspace">
                    <h1 class="title">
                        <img src="/images/floorspace/title.png" alt="Space" />
                    </h1>
                    <img src="/images/floorspace/1.jpg" alt="" class="tile1" />
                    <img src="/images/floorspace/2.jpg" alt="" class="tile2" />
                    <img src="/images/floorspace/hero.jpg" alt="" class="hero" />
                    <img src="/images/floorspace/content1.jpg" alt="" class="content1" />
                    <img src="/images/floorspace/content2.jpg" alt="" class="content2" />
                </article>
            </div>          
        </div>
    </div>
</body>

Now the code I have above does work, however I don't feel it's very clean nor does it seem to execute correctly 100% of the time.

现在我上面的代码确实可以工作,但是我觉得它不是很干净,也不是 100% 的时间都正确执行。

Basically the dilemma I have is I want to be able to execute animateContentIn() afteranimateContentOut() has finished. The only way I've managed to do this is to delay the animateContentIn() function by the time it takes to do the longest animation - in this case it's 1000ms.

基本上我遇到的困境是我希望能够animateContentOut() 完成执行 animateContentIn() 。我设法做到这一点的唯一方法是将 animateContentIn() 函数延迟到执行最长动画所需的时间 - 在本例中为 1000 毫秒。

Isn't there a tidier, more efficient way of writing this??

难道没有一种更整洁、更有效的方式来写这个吗?

回答by Martijn

function someRandomFunction(){
    // This will be executed after myFirstFunction
}

function myFirstFunction(callbackFunction){
    // Do some stuff
    alert(1);
    // Do something slow here

    // Callback when done:
    callbackFunction(some, input);
}
// Usage:
myFirstFunction( someRandomFunction ); // with existing function
myFirstFunction( function(){ alert(1);} ); // anonymous

Note: You can use anonymous functions
Small Demo: http://jsfiddle.net/zcp82/2/

注:可以使用匿名函数
小Demo:http: //jsfiddle.net/zcp82/2/

Another topic with good info: Create a custom callback in JavaScript

另一个具有良好信息的主题:在 JavaScript 中创建自定义回调

回答by Johan

Use a callback?

使用回调?

function executeMyAnimationFunction(complete){
    $('div').animate({ height: '1px' }, 500, complete);
}

Call it like this:

像这样调用它:

executeMyAnimationFunction(function(){
    console.log('animation complete');
});

Or if you insist on using promises:

或者,如果您坚持使用承诺:

executeMyAnimationFunction(){
    var dfd = $.deferred();

    $('div').animate({ height: '1px' }, 500, function(){
        dfd.resolve();
    });

    return dfd.promise();
}

executeMyAnimationFunction().done(function(){
    console.log('animation complete');
});

回答by MarmiK

Please refer Old Post

请参考 Old Post

This seem like duplicate question, if you call multiple function it will call in sequence only

这似乎是重复的问题,如果您调用多个函数,它将仅按顺序调用