3

jQueryのdeferedの使用方法を学んでいますが$.whenと一緒に使用する際の問題に気づきました.notifyWith

を使用せずに例を作成し$.when.notifyWith完全に機能します

function a() {
    var d = new $.Deferred,
        $A = $('#A'),
        $P = $('#P').progressbar();

    setTimeout(function() {
        $A.css('background-color', 'blue');
        d.notifyWith($P, [.5]);
    }, 2000);

    setTimeout(function() {
        $A.text('test');
        d.notifyWith($P, [1]);
        d.resolveWith($P, ['done']);
    }, 4000);

    return d.promise();
}
$('#G').click(function() {
    a().progress(function(x) {
        this.progressbar({
            value: x * 100
        });
    }).done(function(x) {
        alert(x)
    });
});​

デモ:http://jsfiddle.net/NTICompass/3DDSa/3/

内部は.progressthisに設定されて$Pいるため、プログレスバーは正しく移動します。

setTimeout2つのアクションを別々の関数に分割したかったので、それを実行し$.when、promiseを1つに結合するために使用しました。

(function() {
    var $P = $('#P').progressbar();
    window.a = function() {
        var d = new $.Deferred,
            $A = $('#A');

        setTimeout(function() {
            $A.css('background-color', 'blue');
            d.notifyWith($P, [.5]);
            d.resolve('a()');
        }, 2000);

        return d.promise();
    }

    window.b = function() {
        var d = new $.Deferred,
            $A = $('#A');

        setTimeout(function() {
            $A.text('test');
            d.notifyWith($P, [.5]);
            d.resolve('b()');
        }, 4000);

        return d.promise();
    }
}())

$('#G').click(function() {
    $.when(a(), b()).progress(function(x, y) {
        this.progressbar({
            value: ((x || 0) + (y || 0)) * 100
        });
    }).done(function(x, y) {
        alert(x + ' ' + y)
    });
});​

デモ:http://jsfiddle.net/NTICompass/3DDSa/16/

どういうわけかthis中は.progressありません $P。代わりに、それは据え置きオブジェクト(またはpromiseオブジェクト、私にはよくわかりません)です。なぜthis等しくないの$Pですか?

4

2 に答える 2

2

このように記述される理由があるかどうかはわかりませんが、promise1336行目を変更するだけでthis、コードが期待どおりに実行されます。

http://jsfiddle.net/3DDSa/18/

$.when = function(firstParam) {
    var args = [].slice.call(arguments, 0),
        i = 0,
        length = args.length,
        pValues = new Array(length),
        count = length,
        pCount = length,
        deferred = length <= 1 && firstParam && jQuery.isFunction(firstParam.promise) ? firstParam : jQuery.Deferred(),
        promise = deferred.promise();

    function resolveFunc(i) {
        return function(value) {
            args[i] = arguments.length > 1 ? [].slice.call(arguments, 0) : value;
            if (!(--count)) {
                deferred.resolveWith(deferred, args);
            }
        };
    }

    function progressFunc(i) {
        return function(value) {
            pValues[i] = arguments.length > 1 ? [].slice.call(arguments, 0) : value;
            deferred.notifyWith(this, pValues); // this is line 1336
        };
    }
    if (length > 1) {
        for (; i < length; i++) {
            if (args[i] && args[i].promise && jQuery.isFunction(args[i].promise)) {
                args[i].promise().then(resolveFunc(i), deferred.reject, progressFunc(i));
            } else {
                --count;
            }
        }
        if (!count) {
            deferred.resolveWith(deferred, args);
        }
    } else if (deferred !== firstParam) {
        deferred.resolveWith(deferred, length ? [firstParam] : []);
    }
    return promise;
};​

チケットに追加する価値があるかもしれません。

于 2012-08-10T19:58:30.383 に答える
2

これはjQuery1.8.0で修正されており、this実際にはコンテキストの配列です。

$('#G').click(function() {
    var index = 0;
    $.when(a(), b()).progress(function(x, y) {
        this[index++].progressbar({
            value: ((x || 0) + (y || 0)) * 100
        });
    }).done(function(x, y) {
        alert(x + ' ' + y)
    });
});​

デモ:http ://jsfiddle.net/3D4wq/1/( jQueryバグトラッカーのjaubourgに感謝します)

注:内部.progress(および.done)は、arguments.length常に渡される要素の数になる$.whenため、this[arguments.length-1](常に)機能しません。

初めて.progress呼び出されるのarguments[.5, undefined]です。

于 2012-08-14T13:43:14.597 に答える