Javascript Jquery$。何时阻止代码执行和UI更新?

Javascript Jquery$。何时阻止代码执行和UI更新?,javascript,jquery,Javascript,Jquery,我们在单页应用程序中使用JQuery。 我们的增压器是该应用程序的起点,如下所示: define('homebootstrapper', ['jquery', 'config', 'homerouteconfig', 'presenter', 'dataprimer', 'binder'], function ($, config, homeRouteConfig, presenter, dataprimer, binder) { var

我们在单页应用程序中使用JQuery。 我们的增压器是该应用程序的起点,如下所示:

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,那么它是隐式异步的。