1

シングルページアプリケーションで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();
}

$('#busyIndicator').activity(true); には、SVGまたはVMLに基づく進行状況のアニメーションが表示されます。これは、JQuery$.whenを使用する場合を除いてうまく機能します

このサンプルコードを使用して、「LongTimeProcessing」と呼ばれる(通常は増幅によって使用されるバックエンドへのajax呼び出しの代わりに)時間がかかるメソッドを作成しようとしました。

jqueryを使用すると、dataprimerがdef.resolve()で戻るまで、busyindicatorが機能しない(読み取り:が表示されない)ことがわかります。これは、すべてのUI更新をブロックしているように見える場合です。また、LongTimeProcessingメソッドからのカウンター値は、このループからの最後の値のみを示します。実行されますが、表示されることはありません。

何が間違っているのですか?これをどのように処理する必要がありますか。

4

1 に答える 1

3

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();
}

への呼び出しsetTimeoutにより、 への最初の呼び出しの直後に関数を終了iterate()できるようになり、ブラウザのイベント処理ループが UI の更新を処理できるようになり、タイマーが経過すると次の反復に進みます。

于 2013-03-08T09:41:10.913 に答える