jQuery 延迟 - 当多个超时任务完成时
jQuery deferred - when multiple timeout tasks have completed
在使用 $.deferred
、$.when
和 $.done
时遇到一些初期问题。
我正在调用一个方法,该方法在计时器上有几个任务。当此方法中的所有内容(包括计时器中的内容)完成时,我正在寻找回调,因此开始查看 $.when()
和 $.done()
以实现此目的。
我遇到的问题是函数在任务完成之前触发,在调用方法时立即触发。所以,我开始使用 $.deferred
和 resolve()
,但没有成功。没有计时器,我也能做到。
这是我调用方法的地方:
$.when(cover.start()).done(function() {
console.log("Cover has started.");
});
这是整个方法:
return {
other: function() {},
start: function() {
var dfd = $.Deferred();
el.filter.animate({
"opacity": "0.6", "filter": "alpha(opacity=60)"
}, 2000, "easeInOutCirc", function() {
el.share.removeClass('fa-spin');
setTimeout(function() {
el.share.removeClass('fa-cog').addClass('fa-bars');
},1000);
setTimeout(function() {
el.scroll.animate({
"opacity": "1",
"bottom": "40px"
}, 1200, "easeOutBounce", function() {
var pulseOptions = { opacity: "0" };
setTimeout(function() {
el.scroll.pulse(pulseOptions, {
duration : 400,
pulses: 3,
interval: 500,
returnDelay: 800
});
}, 2000);
dfd.resolve();
});
}, 2000);
return dfd.promise();
});
}
} // end return
如您所见,在我最初的尝试失败后,我将 dfd.resolve()
添加到我想要回调的位置并尝试 return 承诺。但是,该功能仍然过早触发。我哪里错了?
问题是,您需要从启动方法return promise
return {
other: function () {},
start: function () {
var dfd = $.Deferred();
el.filter.animate({
"opacity": "0.6",
"filter": "alpha(opacity=60)"
}, 2000, "easeInOutCirc", function () {
el.share.removeClass('fa-spin');
setTimeout(function () {
el.share.removeClass('fa-cog').addClass('fa-bars');
}, 1000);
setTimeout(function () {
el.scroll.animate({
"opacity": "1",
"bottom": "40px"
}, 1200, "easeOutBounce", function () {
var pulseOptions = {
opacity: "0"
};
setTimeout(function () {
el.scroll.pulse(pulseOptions, {
duration: 400,
pulses: 3,
interval: 500,
returnDelay: 800
});
}, 2000);
dfd.resolve();
});
}, 2000);
});
//need to return from start
return dfd.promise();
}
} // end return
不是为了窃取 APJ 的代表'而是出于兴趣,您可以通过利用 .delay()
和 .promise()
来避免回调地狱,这两者都与默认的 "fx" 动画队列有关.
以下几行内容可以解决问题,并且更具可读性:
//animation maps
var maps = [];
maps[0] = { 'opacity':0.6, 'filter':'alpha(opacity=60)' };
maps[1] = { 'opacity':1, 'bottom':'40px' };
maps[2] = { 'opacity':0 };
maps[3] = { 'duration':400, 'pulses':3, 'interval':500, 'returnDelay':800 };
//animation functions
var f = [];
f[0] = function () {
return el.filter.animate(maps[0], 2000, "easeInOutCirc").promise();
};
f[1] = function () {
return el.share.removeClass('fa-spin').delay(1000).promise();
};
f[2] = function () {
return el.share.removeClass('fa-cog').addClass('fa-bars').delay(1000).promise();
};
f[3] = function () {
el.scroll.animate(maps[1], 1200, "easeOutBounce").promise();
}
f[4] = function () {
return el.scroll.delay(2000).promise();//delay() could be called on any element. `el.scroll` is arbitrary.
};
f[5] = function () {
el.scroll.pulse(maps[2], maps[3]);
};
return {
other: function () {},
start: function () {
//animation sequence
var p = f[0]().then(f[1]).then(f[2]).then(f[3]);
p.then(f[4]).then(f[5]);
return p;//<<<< and here's the all important return
}
}
不确定这是否 100% 正确 - 可能需要一些工作。
值得注意的是,这种方法在性能上有利有弊:
- 优点:可重复使用的动画贴图;可重复使用的功能;
- 缺点:更自由地使用 promises 会导致更大的内存峰值。
在使用 $.deferred
、$.when
和 $.done
时遇到一些初期问题。
我正在调用一个方法,该方法在计时器上有几个任务。当此方法中的所有内容(包括计时器中的内容)完成时,我正在寻找回调,因此开始查看 $.when()
和 $.done()
以实现此目的。
我遇到的问题是函数在任务完成之前触发,在调用方法时立即触发。所以,我开始使用 $.deferred
和 resolve()
,但没有成功。没有计时器,我也能做到。
这是我调用方法的地方:
$.when(cover.start()).done(function() {
console.log("Cover has started.");
});
这是整个方法:
return {
other: function() {},
start: function() {
var dfd = $.Deferred();
el.filter.animate({
"opacity": "0.6", "filter": "alpha(opacity=60)"
}, 2000, "easeInOutCirc", function() {
el.share.removeClass('fa-spin');
setTimeout(function() {
el.share.removeClass('fa-cog').addClass('fa-bars');
},1000);
setTimeout(function() {
el.scroll.animate({
"opacity": "1",
"bottom": "40px"
}, 1200, "easeOutBounce", function() {
var pulseOptions = { opacity: "0" };
setTimeout(function() {
el.scroll.pulse(pulseOptions, {
duration : 400,
pulses: 3,
interval: 500,
returnDelay: 800
});
}, 2000);
dfd.resolve();
});
}, 2000);
return dfd.promise();
});
}
} // end return
如您所见,在我最初的尝试失败后,我将 dfd.resolve()
添加到我想要回调的位置并尝试 return 承诺。但是,该功能仍然过早触发。我哪里错了?
问题是,您需要从启动方法return promise
return {
other: function () {},
start: function () {
var dfd = $.Deferred();
el.filter.animate({
"opacity": "0.6",
"filter": "alpha(opacity=60)"
}, 2000, "easeInOutCirc", function () {
el.share.removeClass('fa-spin');
setTimeout(function () {
el.share.removeClass('fa-cog').addClass('fa-bars');
}, 1000);
setTimeout(function () {
el.scroll.animate({
"opacity": "1",
"bottom": "40px"
}, 1200, "easeOutBounce", function () {
var pulseOptions = {
opacity: "0"
};
setTimeout(function () {
el.scroll.pulse(pulseOptions, {
duration: 400,
pulses: 3,
interval: 500,
returnDelay: 800
});
}, 2000);
dfd.resolve();
});
}, 2000);
});
//need to return from start
return dfd.promise();
}
} // end return
不是为了窃取 APJ 的代表'而是出于兴趣,您可以通过利用 .delay()
和 .promise()
来避免回调地狱,这两者都与默认的 "fx" 动画队列有关.
以下几行内容可以解决问题,并且更具可读性:
//animation maps
var maps = [];
maps[0] = { 'opacity':0.6, 'filter':'alpha(opacity=60)' };
maps[1] = { 'opacity':1, 'bottom':'40px' };
maps[2] = { 'opacity':0 };
maps[3] = { 'duration':400, 'pulses':3, 'interval':500, 'returnDelay':800 };
//animation functions
var f = [];
f[0] = function () {
return el.filter.animate(maps[0], 2000, "easeInOutCirc").promise();
};
f[1] = function () {
return el.share.removeClass('fa-spin').delay(1000).promise();
};
f[2] = function () {
return el.share.removeClass('fa-cog').addClass('fa-bars').delay(1000).promise();
};
f[3] = function () {
el.scroll.animate(maps[1], 1200, "easeOutBounce").promise();
}
f[4] = function () {
return el.scroll.delay(2000).promise();//delay() could be called on any element. `el.scroll` is arbitrary.
};
f[5] = function () {
el.scroll.pulse(maps[2], maps[3]);
};
return {
other: function () {},
start: function () {
//animation sequence
var p = f[0]().then(f[1]).then(f[2]).then(f[3]);
p.then(f[4]).then(f[5]);
return p;//<<<< and here's the all important return
}
}
不确定这是否 100% 正确 - 可能需要一些工作。
值得注意的是,这种方法在性能上有利有弊:
- 优点:可重复使用的动画贴图;可重复使用的功能;
- 缺点:更自由地使用 promises 会导致更大的内存峰值。