我正在围绕异步/ ajax调用包装for循环时实现IIFE方法。
var j = 4;
for (var i = 0; i < j; i++) {
(function(cntr) {
asyncCall(function() {
console.log(cntr);
});
})(i);
}
问题是当我在console.log cntr时,我得到了所有的值,但它们有一个随机的顺序。我们假设我有0-4
的for循环。它将以随机顺序打印这些值,如2,1,3,4,0
。每次重新运行代码时,这都会改变。
编辑: 最肯定的问题不是答案。在标记为重复之前请多加注意。我甚至没有使用nodejs ......
答案 0 :(得分:0)
你的asyncCall
没有在一段时间内完成。由于您在同步for循环中开始每个异步调用,因此首先完成的调用将首先记录(换句话说,调用不会彼此等待)。
有两种方法可以解决此问题。第一个是等待每个asyncCall
完成,然后开始下一个,你可以通过递归轻松完成:
var calls = 4
var i = 0
asyncCall(function handler() {
console.log(i)
if (++i < calls) asyncCall(handler)
})
function asyncCall(handler) {
setTimeout(handler, 0)
}
如果每次连续呼叫都取决于前一次呼叫的结果,那么这种方法最有意义。在这种情况下,让每个调用都预先执行是更有效的,但是将结果存储在每个调用完成后记录一次的数组中:
var calls = 4
var done = 0
var i = 0
var results = []
for (var i = 0; i < calls; i++) (function(i) {
asyncCall(function handler() {
results[i] = i // example data
if (++done === calls) complete()
})
})(i)
function complete () {
// Do something with your array of results
results.map(function (e) {
console.log(e)
})
}
function asyncCall(handler) {
setTimeout(handler, Math.random()*10)
}
答案 1 :(得分:0)
一个自动执行的近距离,它看起来像你正在寻找,使用如下:
//<![CDATA[
/* external.js */
var doc, bod, htm, C, T, E; // for use onload elsewhere
addEventListener('load', function(){
doc = document; bod = doc.body; htm = doc.documentElement;
C = function(tag){
return doc.createElement(tag);
}
T = function T(tag){
return doc.getElementsByTagName(tag);
}
E = function(id){
return doc.getElementById(id);
}
addClassName = function(element, className){
var rx = new RegExp('^(.+\s)*'+className+'(\s.+)*$');
if(!element.className.match(rx)){
element.className += ' '+className;
}
return element.className;
}
removeClassName = function(element, className){
element.className = element.className.replace(new RegExp('\s?'+className), '');
return element.className;
}
var outs = doc.getElementsByClassName('output');
for(var i=0,out,l=outs.length; i<l; i++){
(function(){
var out = outs[i], b = false;
out.onclick = function(){
if(b){
removeClassName(out, 'blue'); b = false;
}
else{
addClassName(out, 'blue'); b = true;
}
}
}());
}
}); // close load
//]]>
/* external.css */
html,body{
padding:0; margin:0;
}
.main{
width:980px; margin:0 auto;
}
.output{
width:100px; border:1px solid #000; border-top:0;
}
.output:first-child{
border-top:1px solid #000;
}
.blue{
background:lightblue;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<link type='text/css' rel='stylesheet' href='external.css' />
<script type='text/javascript' src='external.js'></script>
</head>
<body>
<div class='main'>
<div class='output'>Sorry</div>
<div class='output'>This</div>
<div class='output'>Example</div>
<div class='output'>Isn't</div>
<div class='output'>Better</div>
</div>
</body>
</html>
以下是关闭的工作原理。事件实际上会在它们发生时触发,就像onclick一样。当事件触发时你实际上是在循环结束时,所以当发生这种情况时,变量和参数会查找它们最后确定范围的级别。