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
How to force javascript function execute synchronously/sequentially?
提问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 alreadyFadedIn
a flag. At the end of the method call sequentiallyFadeIn(...)
I would like to perform the cleanUp
where 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 alreadyFadedIn
is not getting removed. The cause seems to me is the cleanUp method gets executed asynchronously along with main logic of the sequentiallyFadeIn
method 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 cleanUp
call getting executed after the completion of main logic in the sequentiallyFadedIn
method? Any suggestions?
如何cleanUp
在sequentiallyFadedIn
方法中的主要逻辑完成后执行调用?有什么建议?
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/
回答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/