आप jQuery Deferreds की एक सरणी के साथ कैसे काम करते हैं?


132

मेरे पास एक एप्लिकेशन है जिसे डेटा को एक निश्चित क्रम में लोड करने की आवश्यकता है: रूट URL, फिर स्कीमा, फिर अंत में एप्लिकेशन को स्कीमा के साथ आरंभ करता है और विभिन्न डेटा ऑब्जेक्ट्स के लिए आग्रह करता हूं। जैसे ही उपयोगकर्ता एप्लिकेशन को नेविगेट करता है, डेटा ऑब्जेक्ट लोड हो जाते हैं, स्कीमा के खिलाफ मान्य होते हैं, और प्रदर्शित होते हैं। जैसा कि उपयोगकर्ता डेटा CRUDs करता है, स्कीमा पहले-पास सत्यापन प्रदान करते हैं।

मुझे इनिशियलाइज़ेशन में समस्या हो रही है। मैं रूट ऑब्जेक्ट, $ .when () लाने के लिए एक अजाक्स कॉल का उपयोग करता हूं, और फिर प्रत्येक स्कीमा ऑब्जेक्ट के लिए वादों की एक सरणी बनाता हूं। यह काम करता है। मैं कंसोल में देख रहा हूं।

मैं तब सभी स्कीमाओं के लिए भ्रूण देखता हूं, इसलिए प्रत्येक $ .ajax () कॉल कार्य करता है। fetchschemas () वास्तव में वादों की एक सरणी लौटाता है।

हालाँकि, वह फाइनल जब () क्लॉज़ कभी नहीं होता है और कंसोल पर "DONE" शब्द कभी प्रकट नहीं होता है। Jquery-1.5 का स्रोत कोड प्रतीत होता है कि "null" एक वस्तु के रूप में स्वीकार्य है जो पास में उपलब्ध है। में पारित।

इसने Futures.js का उपयोग करके काम किया। अगर ऐसा नहीं है, तो jQuery के डिफ्रेड्स की एक सरणी कैसे प्रबंधित की जानी चाहिए?

    var fetch_schemas, fetch_root;

    fetch_schemas = function(schema_urls) {
        var fetch_one = function(url) {
            return $.ajax({
                url: url,
                data: {},
                contentType: "application/json; charset=utf-8",
                dataType: "json"
            });
        };

        return $.map(schema_urls, fetch_one);
    };

    fetch_root = function() {
        return $.ajax({
            url: BASE_URL,
            data: {},
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
    };

    $.when(fetch_root()).then(function(data) {
        var promises = fetch_schemas(data.schema_urls);
        $.when.apply(null, promises).then(function(schemas) {
            console.log("DONE", this, schemas);
        });
    });

मेरे पास लगभग एक समान समस्या है, सिवाय इसके कि मुझे "DONE" छपने से पहले fetch_one में प्रत्येक ajax क्वेरी के लिए "सफलता" विधि की आवश्यकता है। आप इसे कैसे करेंगे? मैंने "fetch_one" के बाद .pipe का उपयोग करने की कोशिश की, लेकिन वह काम नहीं कर पाया।
कैम्ब्रिजमाइक

जवाबों:


198

आप देख रहे हैं

$.when.apply($, promises).then(function(schemas) {
     console.log("DONE", this, schemas);
}, function(e) {
     console.log("My ajax failed");
});

यह भी काम करेगा (काम के कुछ मूल्य के लिए, यह टूटे हुए अजाक्स को ठीक नहीं करेगा):

$.when.apply($, promises).done(function() { ... }).fail(function() { ... });` 

आप $इसके बजाय पास करना चाहते हैं nullताकि thisअंदर का $.whenउल्लेख हो jQuery। यह स्रोत के लिए मायने नहीं रखना चाहिए लेकिन यह बेहतर है तो गुजर रहा है null

अपने सभी $ .jax को उनके साथ प्रतिस्थापित करके $.whenऔर नमूना काम करता है

तो यह या तो आपके ajax अनुरोध में एक समस्या है या आपके पास लाने के लिए सरणीch_schemas है।


धन्यवाद। यह सिंटैक्स, किए गए () से भिन्न कैसे होता है।
एल्फ स्टर्नबर्ग

2
@ स्टर्नबर्ग के लिए, .then(a,b) === .done(a).fail(b)यह एक आलसी आशुलिपि है। आप चाहें .done(a).fail(b)तो कॉल कर सकते हैं
Raynos

1
ओह, और $ .when.apply ($, ...) और $ .when.apply (अशक्त, ...) का उपयोग अप्रासंगिक लगता है। jQuery के पास एक वादा () विधि नहीं है, इसलिए यह आंतरिक रूप से उत्पन्न आस्थगित वस्तु (jQuery 1.5, पंक्ति 943) के पक्ष में अनदेखा हो जाता है।
एल्फ स्टर्नबर्ग

1
@ElfSternberg यह वास्तव में अप्रासंगिक है, लेकिन पठनीयता के लिए मुझे दूसरी नज़र लेने की आवश्यकता नहीं है $.when.apply($, ...nullमुझे जाने बनाता है "प्रतीक्षा, क्या?"। यह स्टाइल और कोडिंग प्रैक्टिस की बात है। मुझे यह पुष्टि करने के लिए स्रोत पढ़ना था कि thisjQuery.when के अंदर कोई अशक्त संदर्भ नहीं फेंकेगा!
रेयानोस

7
अशक्त का उपयोग मुझे लगता है कि 'ठीक है, यह एक प्रकार का वर्कअराउंड है' (जो कि यह है), जबकि अगर $ का उपयोग किया गया था तो मेरा ध्यान wtf के बारे में $ $ के लिए सोचने पर लगाया जाएगा।
डेनियल आयटेकिन

53

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

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

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

यहाँ एक समाधान से प्रेरित है when.js की when.all()विधि है कि पतों इन समस्याओं:

// Put somewhere in your scripting environment
if (jQuery.when.all===undefined) {
    jQuery.when.all = function(deferreds) {
        var deferred = new jQuery.Deferred();
        $.when.apply(jQuery, deferreds).then(
            function() {
                deferred.resolve(Array.prototype.slice.call(arguments));
            },
            function() {
                deferred.fail(Array.prototype.slice.call(arguments));
            });

        return deferred;
    }
}

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

$.when.all(promises).then(function(schemas) {
     console.log("DONE", this, schemas); // 'schemas' is now an array
}, function(e) {
     console.log("My ajax failed");
});

@ क्रिस्पीडक - क्या आप जानते हैं कि यदि आप 100% सुनिश्चित हो सकते हैं कि तब ") में" स्कीमा "संस्करण में सरणी तत्वों का क्रम हमेशा उसी क्रम में रहेगा जैसा कि ajax" वादे "संस्करण में कॉल करता है ()?
नेटपिटिका

6
यह केवल बिल्ट-इन jQuery होना चाहिए, लेकिन - jQuery टीम ने कई बार अनुरोध अस्वीकार कर दिया है। इस बीच, लोग यहां सवाल पूछते रहते हैं और jQuery के खिलाफ ऐसे ही टिकट खोलते हैं और हम हर जगह एक यूजरलैंड कार्यान्वयन और / या अजीब कॉल के साथ समाप्त होते हैं apply()... जाने का आंकड़ा।
mindplay.dk

इस समाधान के लिए धन्यवाद! क्या सफल वस्तुओं को प्राप्त करने का एक तरीका है यदि एक (या अधिक) विफल रहा है?
डॉकटोरियस

अच्छी तरह से आप यहाँ सब किया है argumentsअपने तरीके से छिपा हुआ हेरफेर है। फिर से उपयोग करने के लिए महान, लेकिन सौदा करने की "कुरूपता" को संबोधित नहीं करते हैं arguments(आप आसानी से बस कर सकते हैं:var schemas=Array.prototype.slice.call(arguments);)
कायरबेट

2
@ क्रिस्पीडक, deferred.fail(...)पढ़ना नहीं चाहिए deferred.reject(...)?
बॉब एस

19

यदि आप जावास्क्रिप्ट के ईएस 6 संस्करण का उपयोग कर रहे हैं तो एक फैला हुआ ऑपरेटर (...) है जो वस्तुओं के सरणी को अलग किए गए तर्कों के लिए परिवर्तित करता है।

$.when(...promises).then(function() {
 var schemas=arguments; 
};

ES6 स्प्रेड ऑपरेटर के बारे में अधिक https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator यहां खोजें


1
हाँ। हालाँकि हममें से वे Coffeescript या इसके किसी वंशज / नकल करने वाले का उपयोग कर चुके हैं और अब उस परिचालक के पास थोड़ी देर के लिए पहुँच सकते हैं।
एल्फ स्टर्नबर्ग

0

इस कोड के साथ विस्तार होता है:

var rawWhen = $.when
$.when = function(promise) {
    if ($.isArray(promise)) {
        var dfd = new jQuery.Deferred()
        rawWhen.apply($, promise).done(function() {
            dfd.resolve(Array.prototype.slice.call(arguments))
        }).fail(function() {
            dfd.reject(Array.prototype.slice.call(arguments))
        })
        return dfd.promise()
    } else {
        return rawWhen.apply($, arguments)
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.