我觉得答案就在那里,但我不知道该怎么查。我查看了defer
和promise
,但如果我希望将其应用于自身,我不确定如何应用它。
如果update_content()
正在运行,我不希望在第一次完成之前再次调用它。
History.Adapter.bind(window, 'statechange', function() {
var event_state = History.getState();
// bad pseudo code
if(update_content() is running, wait till it is finished(function() {
update_content(event_state.data.html);
}
});
正如您可以通过我可怕的伪代码看到的那样,我希望它等待运行update_content()(如果它已经运行)。一旦完成,它将再次运行。从fadeIn / Outs等完成需要1-3秒,我希望每个状态转换都等到上一个请求完成。
顺便说一下,没有AJAX。我希望它在这个意义上是同步的。
如何将功能延迟运行直至完成运行?
以下是update_content()
代码:
// this function updates page content with ajax and cool effects!
function update_content(data) {
if(data == null) return;
var id = $(data).prop('id'),
content = "#" + id,
header = 0;
// if the header is full, header = 0. if it's tiny, header = 1
if($('#navbar.affix').length) { header = 1; }
// if the page that needs to be loaded is NOT on the page
// this could be #main, #content, etc
if(!$(content).length) {
$(data).hide().appendTo('#main_wrapper');
}
// show the homepage $('#main')
// fades the content viewer out. no positioning is done on the homepage.
if(id == "main") {
if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }
$('#main').siblings(':visible').center(header); // puts visible content on TOP of page
$('#main')// /.center(header)
.show(); // home page goes behind content
$('#main').siblings().fadeOut(600, function() { // fadeout content overlay, and ON COMPLETE
$(this).hide(); // hide that shit
});
if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }
return;
}
// show the content viewer $('#content')
// fades content viewer in
if(id = "content") {
$('#content')
.center(header) // place on top and center
.fadeIn(function() { // fade in, and ON COMPLETE
$('#main').hide(); // quickly remove siblings - DO NOT USE FADE
$(this).uncenter(); // places it static so it is normal
if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }
});
return;
}
}
答案 0 :(得分:2)
首先,您需要知道update_content()
何时完成。为此你可以在你的两个动画上使用一些promises并返回一个在这个函数中启动任何动画时解决的promise(如果没有动画启动,可以立即解决):
// this function updates page content with ajax and cool effects!
// it returns a promise that is resolved when any animations started in this
// function are done
var updateRunning = 0;
function update_content(data) {
if(data == null) [
// return an already resolved promise
return $().promise();
}
++updateRunning;
var id = $(data).prop('id'),
content = "#" + id,
header = 0, p1, p2;
// if the header is full, header = 0. if it's tiny, header = 1
if($('#navbar.affix').length) { header = 1; }
// if the page that needs to be loaded is NOT on the page
// this could be #main, #content, etc
if(!$(content).length) {
$(data).hide().appendTo('#main_wrapper');
}
// show the homepage $('#main')
// fades the content viewer out. no positioning is done on the homepage.
if(id == "main") {
if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }
$('#main').siblings(':visible').center(header); // puts visible content on TOP of page
$('#main')// /.center(header)
.show(); // home page goes behind content
p1 = $('#main').siblings().fadeOut(600, function() { // fadeout content overlay, and ON COMPLETE
$(this).hide(); // hide that shit
}).promise();
if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }
} else {
// show the content viewer $('#content')
// fades content viewer in
if(id == "content") {
p2 = $('#content')
.center(header) // place on top and center
.fadeIn(function() { // fade in, and ON COMPLETE
$('#main').hide(); // quickly remove siblings - DO NOT USE FADE
$(this).uncenter(); // places it static so it is normal
if(header == 1) {
$('body, html').scrollTop(55);
} else {
window.scrollTo(0,0);
}
}).promise();
}
// note that either p1, p2 or both might be undefined here, but
// $.when() should still work for us
return $.when(p1, p2).always(function() {
--updateRunning;
});
}
仅供参考,我还将if (id = "content")
更改为if (id == "content")
,因为我认为您所拥有的是编码错误。
然后,为update_content()
而不是update_content
创建一个队列和一个包装器,并且使用此包装器的想法是,只要update_content()
完成,它就会处理下一个排队的项目。您可以通过维护标志来判断update_content()
是否正在运行。
var queue = [];
function update_content_wrapper(data) {
if (updateRunning !== 0) {
// just queue the data if update already running
queue.push(data);
} else {
update_content(data).always(function() {
// if items in the queue, get the oldest one
if (queue.length) {
update_content_wrapper(queue.shift());
}
});
}
}
然后,您可以在statechange事件上调用包装器函数,它将为您完成所有脏工作:
History.Adapter.bind(window, 'statechange', function() {
var event_state = History.getState();
update_content_wrapper(event_state.data.html);
});
您致电update_content()
的其他任何地方,都应将其切换为致电update_content_wrapper()
。