$ की डिफरेड की एक सरणी में पास करें। जब () [javascript]


Answers

ऊपर दिए गए समाधान (धन्यवाद!) आस्थगित के resolve() विधि को प्रदान किए गए ऑब्जेक्ट को वापस लेने की समस्या को सही तरीके से संबोधित नहीं करता है क्योंकि jQuery कॉल किया done() और fail() व्यक्तिगत पैरामीटर के साथ कॉलबैक, एक सरणी नहीं। इसका मतलब है कि हम arguments सरग्राही-सरणी का उपयोग करना चाहते हैं ताकि सभी हल किए गए / अस्वीकृत ऑब्जेक्ट्स को आस्थगित की सरणी से लौटा दिया जा सके, जो बदसूरत है:

$.when.apply($,deferreds).then(function() {
     var objects=arguments; // The array of resolved objects as a pseudo-array
     ...
};

चूंकि हम स्थगितों की एक सरणी में पारित हो चुके हैं, इसलिए परिणामों की एक सरणी वापस पाने के लिए अच्छा होगा। छद्म-सरणी के बजाय एक वास्तविक सरणी वापस पाने के लिए भी अच्छा होगा ताकि हम Array.sort() जैसी विधियों का उपयोग कर सकें।

यहां एक समाधान है जो when.js से होता है जब सभी समस्याओं को संबोधित करते हैं:

// Put somewhere in your scripting environment
if (typeof jQuery.when.all === 'undefined') {
    jQuery.when.all = function (deferreds) {
        return $.Deferred(function (def) {
            $.when.apply(jQuery, deferreds).then(
                function () {
                    def.resolveWith(this, [Array.prototype.slice.call(arguments)]);
                },
                function () {
                    def.rejectWith(this, [Array.prototype.slice.call(arguments)]);
                });
        });
    }
}

अब आप बस स्थगित / वादों की एक सरणी में पारित कर सकते हैं और अपने कॉलबैक में हल किए गए / अस्वीकृत वस्तुओं की एक सरणी वापस प्राप्त कर सकते हैं, जैसे:

$.when.all(deferreds).then(function(objects) {
    console.log("Resolved objects:", objects);
});
Question

यहां पर क्या हो रहा है इसका एक अनुचित उदाहरण है: http://jsfiddle.net/adamjford/YNGcm/20/

HTML:

<a href="#">Click me!</a>
<div></div>

जावास्क्रिप्ट:

function getSomeDeferredStuff() {
    var deferreds = [];

    var i = 1;
    for (i = 1; i <= 10; i++) {
        var count = i;

        deferreds.push(
        $.post('/echo/html/', {
            html: "<p>Task #" + count + " complete.",
            delay: count
        }).success(function(data) {
            $("div").append(data);
        }));
    }

    return deferreds;
}

$(function() {
    $("a").click(function() {
        var deferreds = getSomeDeferredStuff();

        $.when(deferreds).done(function() {
            $("div").append("<p>All done!</p>");
        });
    });
});

मैं चाहता हूँ "सब किया!" आस्थगित कार्य पूरा होने के बाद सभी प्रकट होने के बाद, लेकिन $.when() डिफर्ड ऑब्जेक्ट की एक सरणी को कैसे प्रबंधित करें, यह जानने में प्रकट नहीं होता है। "सब कुछ कर दिया!" पहले हो रहा है क्योंकि सरणी एक डिफर्ड ऑब्जेक्ट नहीं है, इसलिए jQuery आगे बढ़ता है और मानता है कि यह सिर्फ किया गया है।

मुझे पता है कि ऑब्जेक्ट को ऑब्जेक्ट को $.when(deferred1, deferred2, ..., deferredX) जैसे फ़ंक्शन में पास कर सकते हैं। $.when(deferred1, deferred2, ..., deferredX) लेकिन यह अज्ञात है कि वास्तविक समस्या में निष्पादन में कितने डिफर्ड ऑब्जेक्ट होंगे, जो मैं हल करने की कोशिश कर रहा हूं।




एक साधारण विकल्प के रूप में, जिसकी आवश्यकता नहीं है। $.when.apply या एक array , आप कई समानांतर वादों के लिए एक वादा उत्पन्न करने के लिए निम्न पद्धति का उपयोग कर सकते हैं:

promise = $.when(promise, anotherPromise);

जैसे

function GetSomeDeferredStuff() {
    // Start with an empty resolved promise (or undefined does the same!)
    var promise;
    var i = 1;
    for (i = 1; i <= 5; i++) {
        var count = i;

        promise = $.when(promise,
        $.ajax({
            type: "POST",
            url: '/echo/html/',
            data: {
                html: "<p>Task #" + count + " complete.",
                delay: count / 2
            },
            success: function (data) {
                $("div").append(data);
            }
        }));
    }
    return promise;
}

$(function () {
    $("a").click(function () {
        var promise = GetSomeDeferredStuff();
        promise.then(function () {
            $("div").append("<p>All done!</p>");
        });
    });
});

टिप्पणियाँ:

  • मुझे यह पता चल गया है कि किसी चेन को क्रमशः वादे के बाद वादा किया जाता है, promise = promise.then(newpromise)
  • नकारात्मक पक्ष यह दृश्यों के पीछे अतिरिक्त वायदे वस्तुएं बनाता है और अंत में पारित किए गए किसी भी पैरामीटर बहुत उपयोगी नहीं हैं (क्योंकि वे अतिरिक्त ऑब्जेक्ट्स के अंदर नेस्टेड हैं)। क्या आप चाहते हैं, हालांकि यह छोटी और सरल है
  • ऊपर की ओर इसे कोई सरणी या सरणी प्रबंधन की आवश्यकता नहीं है



मैं $। का उपयोग करने के साथ दूसरे को प्रस्तावित करना चाहता हूं:

  1. हमें अजाक्स फ़ंक्शन जैसे:

    function ajaxFn(someData) {
        this.someData = someData;
        var that = this;
        return function () {
            var promise = $.Deferred();
            $.ajax({
                method: "POST",
                url: "url",
                data: that.someData,
                success: function(data) {
                    promise.resolve(data);
                },
                error: function(data) {
                    promise.reject(data);
                }
            })
            return promise;
        }
    }
  2. कोड का एक भाग जहां हम एजेक्स भेजने के लिए कार्य के सरणी बनाते हैं:

    var arrayOfFn = [];
    for (var i = 0; i < someDataArray.length; i++) {
        var ajaxFnForArray = new ajaxFn(someDataArray[i]);
        arrayOfFn.push(ajaxFnForArray);
    }
  3. और अजाक्स भेजने के साथ फ़ंक्शन कॉल करना:

    $.when(
        $.each(arrayOfFn, function(index, value) {
            value.call()
        })
    ).then(function() {
            alert("Cheer!");
        }
    )



मेरे पास एक ऐसा मामला था, जहां मैं प्रत्येक लूप में पोस्ट कर रहा था और फिर कुछ फ़ील्ड में एजेएक्स से प्राप्त संख्याओं से html मार्कअप सेट कर रहा था। फिर मुझे इन क्षेत्रों के (अब-अपडेट किए गए) मूल्यों का एक योग करने और कुल क्षेत्र में जगह की जरूरत है।

इस प्रकार समस्या यह थी कि मैं सभी नंबरों पर एक योग करने की कोशिश कर रहा था लेकिन एसिंक एजेक्स कॉल से कोई डेटा वापस नहीं आया था। कोड को पुन: उपयोग करने में सक्षम होने के लिए मुझे कुछ फ़ंक्शंस में इस कार्यक्षमता को पूरा करने की आवश्यकता थी। मेरे बाहरी फ़ंक्शन डेटा का इंतजार कर रहा है इससे पहले कि मैं पूरी तरह से अद्यतित डोम के साथ कुछ सामान करता हूं।

    // 1st
    function Outer() {
        var deferreds = GetAllData();

        $.when.apply($, deferreds).done(function () {
            // now you can do whatever you want with the updated page
        });
    }

    // 2nd
    function GetAllData() {
        var deferreds = [];
        $('.calculatedField').each(function (data) {
            deferreds.push(GetIndividualData($(this)));
        });
        return deferreds;
    }

    // 3rd
    function GetIndividualData(item) {
        var def = new $.Deferred();
        $.post('@Url.Action("GetData")', function (data) {
            item.html(data.valueFromAjax);
            def.resolve(data);
        });
        return def;
    }