我在html中有很多div。每个div包含动画或一些js代码,只有当它可见时才调用它:
<button id='start' class='start'>Start</button>
<div class="step1 later">
<div class='red later'>Show first</div>
<div class='aqua later'>Show later</div>
</div>
<div class="step2 later">
<div class='green later'>Show together</div>
<div class='yellow later'>Show together</div>
</div>
我的目标是使用div
课程显示step1
并调用一些js
,然后显示step2
,依此类推。它看起来像滑块。对于此示例,我希望显示step1
然后显示div
red
类,延迟后我想显示aqua
。接下来,我们转到step2
并立即显示两个div:yellow
,green
。我决定使用promises(Q.js)。这是我的代码:
$(function () {
var currentStep = 1,
handlers = {};
$('#start').click(function() {
for(var i = 0; i < 2; i++) {
showStep(currentStep + i);
}
});
function showStep(step) {
var name = 'step' + step;
$('.' + name).show();
handlers[name]();
}
handlers.step1 = function() {
Q().then(function() {
$('.notification').html('Step1 started');
})
.delay(2000)
.then(function() {
showElem('red');
})
.delay(2000)
.then(function() {
showElem('aqua');
});
};
handlers.step2 = function() {
Q().then(function() {
$('.notification').append('Step2 started');
})
.delay(2000)
.then(function() {
showElem('green');
showElem('yellow');
});
};
function showElem(classSelector) {
$('.' + classSelector).fadeIn(100);
}
});
所有动画和延迟作品除了一件事外都能找到。当一个步骤完成时,我的代码不会等待,处理程序几乎同时启动 演示:JSBIN
答案 0 :(得分:2)
使用Q来安排jQuery操作是相当不同寻常的。通过明智地使用其.delay()和.promise()方法,jQuery可以自行完成这项工作。
在下面的代码重写中:
.then()
链showElem()
和showStep()
是不必要的并且消失handlers
被写为对象文字。jQuery(function ($) {
var handlers = {
'step1': function() {
$('.notification').html('<div>Step1 started</div>');
return $(".step1").show(0).delay(2000).promise().then(function() {
return $('.red').fadeIn(100).delay(2000).promise();
}).then(function() {
return $('.aqua').fadeIn(100).promise();
});
},
'step2': function() {
$('.notification').append('<div>Step2 started</div>');
return $(".step2").show(0).delay(2000).promise().then(function() {
return $('.green, .yellow').fadeIn(100);
});
}
};
$('#start').click(function() {
handlers.step1().then(handlers.step2);
});
});
<强> DEMO 强>
修改强>
对于大量处理程序,您可以缩短&#34; start&#34;例程如下:
$('#start').click(function() {
handlers.step1()
.then(handlers.step2)
.then(handlers.step3)
.then(handlers.step4)
.then(handlers.step5)
.then(handlers.step6)
...
;
});
然而,这可能是很多打字,并且不能满足不同数量的处理程序。
解决方案相当简单。
首先,将handlers
写为数组,而不是Object。
var handlers = [
//step 0
function() {
$('.notification').html('<div>Step1 started</div>');
return $(".step1").show(0).delay(2000).promise().then(function() {
return $('.red').fadeIn(100).delay(2000).promise();
}).then(function() {
return $('.aqua').fadeIn(100).promise();
});
},
//step 1
function() {
$('.notification').append('<div>Step2 started</div>');
return $(".step2").show(0).delay(2000).promise().then(function() {
return $('.green, .yellow').fadeIn(100);
});
},
//step 2,
...
//step 3,
...
];
现在,您可以使用Array方法.reduce()
来扫描数组,构建一个承诺链:
$('#start').click(function() {
handlers.reduce(function(promise, handler) {
return promise.then(handler);
}, $.when());
});
在这里,$.when()
是已解决的&#34;种子&#34;承诺让链条开始。
<强> DEMO 强>
答案 1 :(得分:1)
问题出在你最初的“for”循环中,你可以一步到位地执行你所有的“showStep”,而无需等待承诺。
你可以这样做:
$('#start').click(function() {
showStep(1);
});
function showStep(step) {
var name = 'step' + step;
$('.' + name).show();
handlers[name]().then(function() {
if (step < 2) {
showStep(step+1);
}
});
}
让你的处理人员回报承诺。