2011-04-01 12 views
22

$.when() का उपयोग करते समय मुझे एक अप्रत्याशित परिणाम मिल रहा है जब स्थगित संचालन में से कोई भी सफल नहीं होता है।

इस जावास्क्रिप्ट को लें, जिसने 2 स्थगित किए हैं। पहला सफल होता है और दूसरा विफल रहता है।

var f1 = function() { 
    return $.Deferred(function(dfd) { 
     dfd.resolve('123 from f1'); 
    }).promise(); 
}; 

var f2 = function() { 
    return $.Deferred(function(dfd) { 
     dfd.reject('456 from f2'); 
    }).promise(); 
}; 

$.when(f1(), f2()) 
    .then(function(f1Val, f2Val) { 
     alert('success! f1, f2: ' + JSON.stringify([f1Val, f2Val])); 
    }) 
    .fail(function(f1Val, f2Val) { 
     alert('fail! f1, f2: ' + JSON.stringify([f1Val, f2Val])); 
    }); 

भागो यह अपने आप: http://jsfiddle.net/r2d3j/2/

मैं fail! f1, f2: ["456 from f2", null]

मिल समस्या यह है कि .fail() कॉलबैक में f2() अस्वीकृति के साथ भेजे गए मान, पहला तर्क है, जहां मैं उम्मीद करने से कराई जा रही है f1Value। जिसका अर्थ है कि मेरे पास वास्तव में यह जानने का कोई तरीका नहीं है कि किस अव्यवस्थित वस्तु ने वास्तव में reject() पोस्ट किया है, और मुझे यह भी नहीं पता कि विफलता डेटा वास्तव में किस ऑपरेशन से संबंधित है।

मुझे उम्मीद थी कि .fail() तर्कों को null, '456 from f2' मिलेगा क्योंकि पहले स्थगित विफल नहीं हुआ था। या क्या मैं यहां सही तरीके से स्थगित नहीं कर रहा हूं?

मुझे कैसे पता चलेगा कि कौन से स्थगित विफल हुए, और कॉल अस्वीकरण में तर्क आदेश का सम्मान नहीं किया गया है, जो अस्वीकृति तर्क विफल हैं?

उत्तर

5

आंतरिक रूप से, "अस्वीकार" और "असफल" पथ दो पूरी तरह से अलग कतारों से संभाले जाते हैं, इसलिए यह आपके द्वारा अपेक्षित तरीके से काम नहीं करता है।

यह जानने के लिए कि "कब()" समूह से कौन सा मूल डिफरर्ड विफल रहा है, आप उन्हें ऑब्जेक्ट शाब्दिक या कुछ के हिस्से के रूप में ".ject()" कॉल के साथ स्वयं को पास कर सकते हैं।

+0

हम्म, मैं इसे कैसे डिजाइन नहीं करता था, लेकिन मुझे लगता है कि मेरा परिणाम समझ में आता है। –

21

$.when() विफल कॉलबैक निष्पादित करेगा (दूसरा पैरामीटर then() पर उत्तीर्ण) तत्काल यदि कोई भी पैरामीटर विफल रहता है। यह डिजाइन द्वारा है। प्रलेखन के शब्दों में:

http://api.jquery.com/jQuery.when/

बहु-Deferreds मामले में जहां Deferreds में से एक को अस्वीकार कर दिया गया है, jQuery.when तुरंत अपने गुरु स्थगित के लिए failCallbacks सक्रिय करता है। ध्यान दें कि कुछ बिंदुओं को अभी भी उस बिंदु पर अनसुलझा किया जा सकता है। यदि आपको इस मामले के लिए अतिरिक्त प्रसंस्करण करने की आवश्यकता है, जैसे किसी भी अधूरे AJAX अनुरोधों को रद्द करना, आप अंतर्निहित jqXHR ऑब्जेक्ट्स को बंद करने में विफल रख सकते हैं और विफल/जांच में उन्हें रद्द/रद्द कर सकते हैं।

वास्तव में कॉलबैक प्राप्त करने का कोई अंतर्निहित तरीका नहीं है जो तब तक प्रतीक्षा करता है जब तक कि उनकी सफलता/विफलता स्थिति के बावजूद उनमें से सभी समाप्त नहीं हो जाते हैं।

तो, मैं आप के लिए एक $.whenAll() बनाया :)
यह हमेशा इंतजार कर रहा है जब तक उन सभी को हल, एक ही रास्ता या अन्य:

http://jsfiddle.net/InfinitiesLoop/yQsYK/51/

$.whenAll(a, b, c) 
    .then(callbackUponAllResolvedOrRejected); 
+1

आप कहते हैं "तत्काल() कॉलबैक तुरंत निष्पादित करेगा", लेकिन आपके द्वारा उद्धृत उद्धरण में कहा गया है "तुरंत विफल विफलताएं" - तो यह कौन है? '\ -:' – hippietrail

+2

@hippietrail यह दोनों है। तब() स्थगित होने पर आग "हल" या "अस्वीकार" होती है। यह एक अस्वीकृति के रूप में वर्गीकृत करता है, इसलिए यह आग लगती है। – InfinitiesLoop

+2

नहीं, यह तब कॉलबैक को आग नहीं करता है .. यह विफल कॉलबैक को सक्रिय करता है। (जो तकनीकी रूप से 'दूसरा' कॉलबैक 'तत्काल' हो सकता है, लेकिन किसी भी मामले में यह 'तत्काल' कॉलबैक जैसा नहीं है जो आपके उत्तर को पढ़ने वाले अधिकांश लोग 'सफलता' कॉलबैक मानेंगे)। – hasen

0

मैं इस एक ही समस्या का सामना करना पड़ा गया है , और मैंने .always कॉलबैक का उपयोग करके और स्थगित वस्तुओं की मेरी सरणी का निरीक्षण करके इसका सामना किया।मैं ajax कॉल की संख्या ज्ञात नहीं था, इसलिए मैं निम्नलिखित करना था:

// array of ajax deletes 
var deletes = []; 
$checkboxes.each(function() { 
    deletes.push(deleteFile(this)); 
}); 

$.when.apply($, deletes) 
    .always(function() { 
     // unfortunately .fail shortcircuits and returns the first fail, 
     // so we have to loop the deferred objects and see what happened. 

     $.each(deletes, function() { 
      this.done(function() { 
       console.log("done"); 
      }).fail(function() { 
       console.log("fail"); 
      }); 
     }); 
    }); 

deleteFile विधि एक वादा है, जो .done या .fail कॉलबैक है देता है।

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

मैंने अभी यह कोशिश की, और दुर्भाग्यवश मुझे यह जांचने के लिए एक अंतराल टाइमर डालना पड़ा कि वे वास्तव में स्थगित वस्तुओं पर मेरे $ .Each के बाद किए गए थे। यह अजीब और counterintuitive लगता है।

फिर भी इन deferreds समझने की कोशिश कर!

+0

यदि कोई भी स्थगित विफल रहता है तो हमेशा "शॉर्ट-सर्किट" भी होगा। – Chloraphil

0

http://jsfiddle.net/InfinitiesLoop/yQsYK/

यह हमेशा अस्वीकार कर देंगे यदि एक से अधिक आदानों दिया। rejected = true;rejected |= reject;

+0

धन्यवाद, मैंने केवल इस जवाब को देखा क्योंकि यह मेरे उत्तर पर नहीं बनाया गया था। मैंने इसे ठीक किया ... बेहतर देर से कभी नहीं? – InfinitiesLoop

संबंधित मुद्दे