javascript 如何强制javascript函数同步/顺序执行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13543553/
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-26 19:06:43  来源:igfitidea点击:

How to force javascript function execute synchronously/sequentially?

javascriptjqueryhtmlasynchronous

提问by Atharva

I am creating a utility method which helps fading the elements sequentially with jQuery. As you can see in the below code I am adding an extra class as alreadyFadedIna flag. At the end of the method call sequentiallyFadeIn(...)I would like to perform the cleanUpwhere I want to remove the flag class which I added in the selected elements inside the sequentiallyFadeIn(...)method.

我正在创建一个实用方法,它有助于使用 jQuery 按顺序淡化元素。正如您在下面的代码中看到的,我添加了一个额外的类作为alreadyFadedIn标志。在方法调用结束时,sequentiallyFadeIn(...)我想执行cleanUp我想删除在sequentiallyFadeIn(...)方法内的选定元素中添加的标志类的位置。

<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$(document).ready(function() {

    function sequentialFadeIn(selectorText, speed, display, callBack) {

        display = typeof display !== 'undefined' ? display : "block";

        function helper() {
            nextElementToFadeIn = $(selectorText).not(".alreadyFadedIn").first();
            nextElementToFadeIn.fadeIn(speed, function() {
                $(this).addClass("alreadyFadedIn");
                helper();
            }).css("display", display);
        }
        helper();

        callBack(selectorText);      
    }
    sequentialFadeIn(".toBeFaddedIn", "slow", "inline-block",function cleanUp(selectorText1){
            $(selectorText1).removeClass("alreadyFadedIn");
            console.log("Clean up has been performed.");
                    console.log("Selector Text: " +selectorText1);

        } );

});

</script>

</head>
<body><style media="screen" type="text/css">
.hello {
    background-color: blue;
    height:50px;
    width: 50px;
    display: none;

}
</style>

<div class="hello toBeFaddedIn"></div>
<div class="hello toBeFaddedIn"></div>
<div class="hello toBeFaddedIn"></div>
<div class="hello toBeFaddedIn"></div>
<div class="hello toBeFaddedIn"></div>

</body></html>

While looking at the inspect element I notice that class alreadyFadedInis not getting removed. The cause seems to me is the cleanUp method gets executed asynchronously along with main logic of the sequentiallyFadeInmethod which is in helper(). You can also notice the log message "Clean up has been performed." getting printed even before the divs have completed fading in.

在查看检查元素时,我注意到类alreadyFadedIn没有被删除。原因在我看来是清理方法被异步随着主逻辑执行sequentiallyFadeIn这是方法helper()。您还可以注意到日志消息“已执行清理”。甚至在 div 完成淡入之前就被打印出来。

How can I make the cleanUpcall getting executed after the completion of main logic in the sequentiallyFadedInmethod? Any suggestions?

如何cleanUpsequentiallyFadedIn方法中的主要逻辑完成后执行调用?有什么建议?

Code on jsfiddle: http://jsfiddle.net/BztLx/11/

jsfiddle 上的代码:http: //jsfiddle.net/BztLx/11/

回答by Asad Saeeduddin

You need to check whether any elements remain to be faded in. If no elements remain, call the cleanup callback. Here is how I implemented it:

需要检查是否还有元素需要淡入,如果没有元素,则调用cleanup回调。这是我如何实施它:

    if ($(selectorText).is(":not(.alreadyFadedIn)")) {

        //Your main logic
        nextElementToFadeIn = $(selectorText).not(".alreadyFadedIn").first();
        nextElementToFadeIn.fadeIn(speed, function() {
            $(this).addClass("alreadyFadedIn");
            helper();
        }).css("display", display);

    } else {

        //No elements remain, cleanup time
        callBack(selectorText);
    }

In the outer condition I check whether there is at least one element that is not faded in, otherwise I invoke the callback.

在外部条件中,我检查是否至少有一个元素没有淡入,否则我调用回调。

Demonstration: http://jsfiddle.net/BztLx/12/

演示:http: //jsfiddle.net/BztLx/12/

回答by I Hate Lazy

Easier, cleaner and faster if you just rewrite your code something like this...

如果您只是像这样重写代码,则更容易、更清晰、更快……

$(document).ready(function() {

    function sequentialFadeIn(selectorText, speed, display, callBack) {

        display = display || "block";

        var els = $(selectorText),
              i = 0;

        (function helper() {
            els.eq(i++).fadeIn(speed, helper).css("display", display);
            if (callback && i === els.length)
                callback(selectorText); // Not really needed any more
        })();
    }

    sequentialFadeIn(".toBeFaddedIn", "slow", "inline-block", function cleanUp(selectorText1){
        // not really needed any more
       //  $(selectorText1).removeClass("alreadyFadedIn");
    });
});


DEMO:http://jsfiddle.net/BztLx/15/

演示:http ://jsfiddle.net/BztLx/15/

You were doing waymore DOM selection than needed.

你正在做的方式比需要更多的DOM的选择。

回答by Christophe

To expand on my comment, here is a simplified version that doesn't use an additional class:

为了扩展我的评论,这是一个不使用附加类的简化版本:

function fadeThenNext(element){
    element.fadeIn("fast", function() {
        element=element.next(".toBeFaddedIn");
        if (element.length) fadeThenNext(element);
    });
}
fadeThenNext($(".toBeFaddedIn").first());

demo: http://jsfiddle.net/BztLx/17/

演示:http: //jsfiddle.net/BztLx/17/

[Update]A more generic version if the elements are not siblings:

[更新]如果元素不是兄弟元素,则使用更通用的版本:

function fadeSequence(elements){
    elements.first().fadeIn("fast", function() {
        fadeSequence(elements.slice(1));
    });
}
fadeSequence($(".toBeFaddedIn"));

?fiddle: http://jsfiddle.net/BztLx/22/

?小提琴:http: //jsfiddle.net/BztLx/22/