Javascript Jquery$。何时阻止代码执行和UI更新?
我们在单页应用程序中使用JQuery。 我们的增压器是该应用程序的起点,如下所示:Javascript Jquery$。何时阻止代码执行和UI更新?,javascript,jquery,Javascript,Jquery,我们在单页应用程序中使用JQuery。 我们的增压器是该应用程序的起点,如下所示: define('homebootstrapper', ['jquery', 'config', 'homerouteconfig', 'presenter', 'dataprimer', 'binder'], function ($, config, homeRouteConfig, presenter, dataprimer, binder) { var
define('homebootstrapper',
['jquery', 'config', 'homerouteconfig', 'presenter', 'dataprimer', 'binder'],
function ($, config, homeRouteConfig, presenter, dataprimer, binder) {
var
run = function () {
$('#busyIndicator').activity(true);
$.when(dataprimer.fetch())
.done(function () {
// $('#busyIndicator').activity(false);
});
};
return {
run: run
};
});
define('dataprimer',
['ko', 'datacontext', 'config'],
function (ko, datacontext, config) {
var logger = config.logger,
fetch = function () {
return $.Deferred(function (def) {
console.log('in deferred');
$.when(LongTimeProcessing())
.pipe(function () {
logger.success('Fetched data');
})
.fail(function () { def.reject(); })
.done(function () { def.resolve(); });
}).promise();
};
return {
fetch: fetch
};
});
function LongTimeProcessing(options) {
console.log('in when');
return $.Deferred(function (def) {
var results = options;
for (var i = 0; i < 10; i++) {
var x = i;
$('#counter').html(x);
}
def.resolve(results);
}).promise();
}
正在调用的dataprimer如下所示:
define('homebootstrapper',
['jquery', 'config', 'homerouteconfig', 'presenter', 'dataprimer', 'binder'],
function ($, config, homeRouteConfig, presenter, dataprimer, binder) {
var
run = function () {
$('#busyIndicator').activity(true);
$.when(dataprimer.fetch())
.done(function () {
// $('#busyIndicator').activity(false);
});
};
return {
run: run
};
});
define('dataprimer',
['ko', 'datacontext', 'config'],
function (ko, datacontext, config) {
var logger = config.logger,
fetch = function () {
return $.Deferred(function (def) {
console.log('in deferred');
$.when(LongTimeProcessing())
.pipe(function () {
logger.success('Fetched data');
})
.fail(function () { def.reject(); })
.done(function () { def.resolve(); });
}).promise();
};
return {
fetch: fetch
};
});
function LongTimeProcessing(options) {
console.log('in when');
return $.Deferred(function (def) {
var results = options;
for (var i = 0; i < 10; i++) {
var x = i;
$('#counter').html(x);
}
def.resolve(results);
}).promise();
}
define('dataprimer',
['ko','datacontext','config'],
函数(ko、datacontext、config){
var logger=config.logger,
fetch=函数(){
return$.Deferred(函数(def)){
console.log(“延迟登录”);
$.when(LongTimeProcessing())
.pipe(函数(){
logger.success('Fetched data');
})
.fail(函数(){def.reject();})
.done(函数(){def.resolve();});
}).promise();
};
返回{
取回
};
});
函数长时间处理(选项){
console.log('in when');
return$.Deferred(函数(def)){
var结果=期权;
对于(变量i=0;i<10;i++){
var x=i;
$('#counter').html(x);
}
确定(结果);
}).promise();
}
行$('busyIndicator').activity(true)代码>
应显示基于SVG或VML的进度动画。这很好,除了使用JQuery$时
通过这个示例代码,我们尝试创建一个需要一些时间的方法,称为“LongTimeProcessing”(而不是通常通过amplify使用的对后端的ajax调用)
我们看到,当我们使用jquery时,直到dataprimer返回def.resolve()时,busyindicator才会工作(read:不显示)。这似乎会阻止所有UI更新。此外,LongTimeProcessing方法中的计数器值仅显示此循环中的最后一个值。它被执行,但它永远不可见
我们做错了什么?我们应该如何处理这个问题。您必须服从事件处理循环,以允许UI更新和处理未完成的事件。只有当您自己的代码完成执行时,才会发生这种情况
您的LongTimeProcessing
函数不会执行此操作,它会启动一个循环,并且在该循环完成之前不会将控制权返回到浏览器
通过使用setTimeout
处理循环迭代,您可以实现您想要的:
function LongTimeProcessing(options) {
console.log('in when');
return $.Deferred(function (def) {
var results = options;
var i = 0;
(function iterate() {
$('#counter').html(i);
if (i < 10) {
++i;
setTimeout(iterate, 250);
} else {
def.resolve(results);
}
})();
}).promise();
}
函数长时间处理(选项){
console.log('in when');
return$.Deferred(函数(def)){
var结果=期权;
var i=0;
(函数iterate(){
$('#counter').html(i);
如果(i<10){
++一,;
setTimeout(迭代,250);
}否则{
确定(结果);
}
})();
}).promise();
}
调用setTimeout
允许函数在第一次调用iterate()
后立即终止,允许浏览器的事件处理循环处理UI更新,然后在计时器过期时进入下一次迭代。非常有效,谢谢。我假设amplify在调用后端时默认会这样做?@Thomas不知道,但是如果对后端的调用使用AJAX,那么它是隐式异步的。