मुझे jQuery स्थगित "तब" विधि का उपयोग कब करना चाहिए और मुझे "पाइप" विधि का उपयोग कब करना चाहिए?


97

jQuery के Deferredदो कार्य हैं जिनका उपयोग फ़ंक्शंस की एसिंक्रोनस चेनिंग को लागू करने के लिए किया जा सकता है:

then()

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

Callbacks एक फ़ंक्शन, या फ़ंक्शन का सरणी, जिसे तब स्थगित किया जाता है जब कॉल किया जाता है।
असफलता एक कार्य, या फ़ंक्शन की सरणी, जिसे तब स्थगित किया जाता है, जब इसे अस्वीकृत कर दिया जाता है।

pipe()

deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise

फ़िल्टर एक वैकल्पिक फ़ंक्शन जिसे डीफ़रड के हल होने पर कहा जाता है।
विफलफिल्टर एक वैकल्पिक फ़ंक्शन जिसे डेफ़र्ड अस्वीकार होने पर कहा जाता है।

मुझे पता then()है कि थोड़ी देर के आसपास हो गया है, pipe()इसलिए बाद में कुछ अतिरिक्त लाभ जोड़ना चाहिए, लेकिन क्या फर्क पड़ता है, इससे मुझे पता चलता है । दोनों बहुत अधिक कॉलबैक मापदंडों को लेते हैं, हालांकि वे नाम में भिन्न होते हैं Deferredऔर वापस लौटने और Promiseमामूली लगने के बीच का अंतर ।

मैंने आधिकारिक डॉक्स को बार-बार पढ़ा है, लेकिन हमेशा उन्हें "घना" पाते हैं कि वास्तव में मेरे सिर को चारों ओर लपेटने के लिए और खोज ने एक विशेषता या दूसरे की बहुत चर्चा की है, लेकिन मुझे ऐसा कुछ भी नहीं मिला है जो वास्तव में अलग से स्पष्ट करता हो प्रत्येक के पेशेवरों और विपक्ष।

तो कब उपयोग करना बेहतर है thenऔर कब उपयोग करना बेहतर है pipe?


इसके अलावा

फेलिक्स के उत्कृष्ट उत्तर ने वास्तव में यह स्पष्ट करने में मदद की है कि ये दोनों कार्य कैसे भिन्न हैं। लेकिन मुझे आश्चर्य है कि अगर ऐसा समय हो, जब कार्यक्षमता इसके then()लिए बेहतर हो pipe()

यह स्पष्ट है कि pipe()यह अधिक शक्तिशाली है then()और ऐसा लगता है कि पूर्व कुछ भी कर सकता है जो बाद में कर सकता है। उपयोग करने का एक कारण यह then()हो सकता है कि इसका नाम उसी डेटा को संसाधित करने वाले कार्यों की श्रृंखला की समाप्ति के रूप में अपनी भूमिका को दर्शाता है।

लेकिन क्या कोई ऐसा उपयोग मामला है जिसके then()लिए मूल को वापस करने की आवश्यकता होती है Deferredजो pipe()इसे वापस करने के कारण नहीं किया जा सकता है Promise?


1
मैंने कुछ समय के लिए इस बारे में सोचा, लेकिन tbh, मैं किसी भी उपयोग के मामले के बारे में नहीं सोच सकता। यदि आपको उनकी आवश्यकता नहीं है (मैं नहीं जानता कि वे कैसे आंतरिक रूप से एक साथ जंजीर में बंधे हैं) तो नए वादे वस्तुओं को बनाने के लिए यह सिर्फ एक उपरि हो सकता है। उन्होंने कहा, निश्चित रूप से ऐसे लोग हैं, जिन्हें मुझसे बेहतर समझ है।
फेलिक्स क्लिंग

6
इस सवाल में रुचि रखने वाला कोई भी व्यक्ति jQuery बग ट्रैकर पर टिकट # 11010 में निश्चित रूप से दिलचस्पी लेगा
hippietrax

जवाबों:


103

चूँकि jQuery 1.8 .then समान व्यवहार करता है .pipe:

पदावनति सूचना: jQuery 1.8 के रूप में, deferred.pipe()विधि पदावनत है। deferred.then()विधि है, जो इसे बदल देता है, बजाय प्रयोग किया जाना चाहिए।

तथा

JQuery 1.8 के रूप में , deferred.then()विधि एक नया वादा लौटाती है जो एक फ़ंक्शन के माध्यम से आस्थगित की स्थिति और मूल्यों को फ़िल्टर कर सकती है, अब-पदावनत deferred.pipe()विधि की जगह।

नीचे दिए गए उदाहरण अभी भी कुछ के लिए उपयोगी हो सकते हैं।


वे विभिन्न उद्देश्यों की पूर्ति करते हैं:

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

  • आप किसी भी तरह .pipe()से (पूर्व) फ़िल्टर का उपयोग करेंगे । कॉलबैक के रिटर्न मान को कॉलबैक और कॉलबैक के .pipe()तर्क के रूप में पारित किया जाएगा । यह एक और आस्थगित वस्तु भी लौटा सकता है और इस आस्थगित पर निम्नलिखित कॉलबैक पंजीकृत किए जाएंगे।donefail

    यही कारण है कि के साथ ऐसा नहीं है .then()(या .done(), .fail()), पंजीकृत कॉलबैक की वापसी मान सिर्फ ध्यान नहीं दिया जाता।

तो ऐसा नहीं है कि आप या तो उपयोग करते हैं .then() या .pipe() । आप एक ही उद्देश्य के लिए उपयोग कर सकते हैं .pipe(), .then()लेकिन कांसेप्ट धारण नहीं करता है।


उदाहरण 1

कुछ ऑपरेशन का परिणाम वस्तुओं की एक सरणी है:

[{value: 2}, {value: 4}, {value: 6}]

और आप न्यूनतम और अधिकतम मानों की गणना करना चाहते हैं। मान लें कि हम दो doneकॉलबैक का उपयोग करते हैं :

deferred.then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var min = Math.min.apply(Math, values);

   /* do something with "min" */

}).then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var max = Math.max.apply(Math, values);

   /* do something with "max" */ 

});

दोनों मामलों में आपको सूची पर पुनरावृत्त करना होगा और प्रत्येक ऑब्जेक्ट से मान निकालना होगा।

क्या किसी तरह से पहले से मान निकालना बेहतर नहीं होगा ताकि आपको व्यक्तिगत रूप से दोनों कॉलबैक में ऐसा न करना पड़े? हाँ! और हम इसका उपयोग कर सकते हैं .pipe():

deferred.pipe(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    return values; // [2, 4, 6]

}).then(function(result) {
    // result = [2, 4, 6]

    var min = Math.min.apply(Math, result);

    /* do something with "min" */

}).then(function(result) {
    // result = [2, 4, 6]

    var max = Math.max.apply(Math, result);

    /* do something with "max" */

});

जाहिर है यह एक बना हुआ उदाहरण है और इस समस्या को हल करने के कई (शायद बेहतर) तरीके हैं, लेकिन मुझे उम्मीद है कि यह इस बिंदु को दिखाता है।


उदाहरण 2

अजाक्स कॉल पर विचार करें। कभी-कभी आप पिछले एक के पूरा होने के बाद एक अजाक्स कॉल शुरू करना चाहते हैं। एक तरीका doneकॉलबैक के अंदर दूसरा कॉल करना है :

$.ajax(...).done(function() {
    // executed after first Ajax
    $.ajax(...).done(function() {
        // executed after second call
    });
});

अब मान लेते हैं कि आप अपने कोड को अलग करना चाहते हैं और इन दो अजाक्स कॉलों को एक फंक्शन के अंदर रखना चाहते हैं:

function makeCalls() {
    // here we return the return value of `$.ajax().done()`, which
    // is the same deferred object as returned by `$.ajax()` alone

    return $.ajax(...).done(function() {
        // executed after first call
        $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

आप अन्य कोड की अनुमति देने के लिए आस्थगित ऑब्जेक्ट का उपयोग करना चाहते हैं, जो दूसरे अजाक्स कॉल के makeCallsलिए कॉलबैक संलग्न करने के लिए कॉल करता है, लेकिन

makeCalls().done(function() {
    // this is executed after the first Ajax call
});

वांछित प्रभाव नहीं होगा क्योंकि दूसरी कॉल एक doneकॉलबैक के अंदर की जाती है और बाहर से सुलभ नहीं होती है।

समाधान .pipe()इसके बजाय उपयोग करना होगा :

function makeCalls() {
    // here we return the return value of `$.ajax().pipe()`, which is
    // a new deferred/promise object and connected to the one returned
    // by the callback passed to `pipe`

    return $.ajax(...).pipe(function() {
        // executed after first call
        return $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

makeCalls().done(function() {
    // this is executed after the second Ajax call
});

उपयोग करके .pipe()अब आप कॉल के वास्तविक प्रवाह / क्रम को उजागर किए बिना कॉलबैक को "इनर" अजाक्स कॉल में जोड़ना संभव बना सकते हैं।


सामान्य तौर पर, आस्थगित ऑब्जेक्ट आपके कोड को डिकूप करने का एक दिलचस्प तरीका प्रदान करते हैं :)


आह हां मैंने अनदेखी की कि pipeफ़िल्टरिंग कर सकते हैं जो thenनहीं कर सकते। लेकिन इन विषयों के गूग्लिंग में ऐसा लगता है कि उन्होंने इसके pipeबजाय इसे बुलाना चुना filterक्योंकि माना जाता है कि फ़िल्टरिंग एक बोनस अतिरिक्त है जो इसके साथ आया था जबकि pipeअधिक स्पष्ट रूप से इसके वास्तविक उद्देश्य को इंगित करता है। इसलिए ऐसा लगता है कि फ़िल्टरिंग के अलावा अन्य अंतर भी होने चाहिए। (फिर मैं स्वीकार करता हूं कि मैं वास्तव में आपके उदाहरणों के साथ भी फ़िल्टरिंग सुविधा को नहीं समझता हूं। वैसे भी होना result values;चाहिए return values;?)
हिप्पेट्रिल

जब मैं कहता हूं कि मैं आपके उदाहरणों को नहीं समझता, तो क्या यह कुछ ऐसा है: ऊपरी उदाहरण में, दोनों .then()को एक ही डेटा प्राप्त होता है resultजिसमें आप हर बार फ़िल्टर करते हैं; जबकि निचले उदाहरण में, पास होने से पहले .pipe()इसमें resultसे कुछ डेटा को हटा देता है , जैसा कि resultबाद के दो .then()को प्राप्त होगा?
हिप्पिट्रैएल

1
@ ह्पीपिट्रिल: मैंने इस बीच अपना जवाब अपडेट किया और इसके अन्य उद्देश्यों को भी शामिल किया .pipe()। यदि कॉलबैक एक स्थगित ऑब्जेक्ट लौटाता है, तो बाद में किया गया या विफल कॉलबैक उस ऑब्जेक्ट के लिए पंजीकृत किया जाएगा। मैं एक और उदाहरण शामिल करूंगा। संपादित करें: अपनी दूसरी टिप्पणी के बारे में: हाँ।
फेलिक्स क्लिंग

तो एक अंतर यह है कि डेटा बहती है के माध्यम से pipe() , जबकि then()एक की तरह है पत्ती नोड जिसके अंत में आप अपने डेटा का उपयोग करना चाहिए पर और इसे आगे पर प्रवाहित नहीं होता है, और तथ्य यह है कि बावजूद कि then()रिटर्न एक Deferredयह वास्तव में नहीं किया जाता है / उपयोगी? यदि यह सही है तो यह स्पष्ट करने में मदद कर सकता है कि /* do something with "min"/"max" */प्रत्येक ".then () क्लॉज" में कुछ को शामिल किया जाए ।
हिप्पिट्रैएल

1
कोई चिंता नहीं :) यह पूरी तरह से स्थगित वस्तुओं और उनके तरीकों के काम करने के लिए मुझे कुछ समय लगा। लेकिन एक बार जब आप इसे समझ लेते हैं, तो यह अब मुश्किल नहीं लगता है। मैं इस बात से सहमत हूं कि प्रलेखन को शायद आसान तरीके से लिखा जा सकता है।
फेलिक्स क्लिंग

7

कोई इस मामले में जहां आप का उपयोग करना चाहिए then()से अधिक pipe()। आप हमेशा उस मान को अनदेखा करने का विकल्प चुन सकते हैं जो pipe()पास हो जाएगा । उपयोग करने के लिए थोड़ा सा प्रदर्शन हिट हो सकता है pipe- लेकिन यह संभव नहीं है।

तो ऐसा लग सकता है कि आप हमेशा pipe()दोनों मामलों में उपयोग कर सकते हैं । हालाँकि , उपयोग करके pipe(), आप अपने कोड को पढ़ने वाले अन्य लोगों से संवाद कर रहे हैं (अपने आप को, अब से छह महीने बाद) कि वापसी मूल्य के लिए कुछ महत्व है। यदि आप इसे छोड़ रहे हैं, तो आप इस शब्दार्थ निर्माण का उल्लंघन कर रहे हैं।

यह एक ऐसे फंक्शन की तरह है जो एक ऐसे मूल्य को लौटाता है जिसका कभी उपयोग नहीं किया जाता है: भ्रमित करना।

इसलिए then()जब आपको चाहिए, और pipe()जब आपको उपयोग करना चाहिए ...


3
मुझे K. स्कॉट एलन के ब्लॉग पर दो का उपयोग करके एक वास्तविक जीवन का उदाहरण मिला है, "एक्सपेरिमेंट इन राइटिंग": जियोलोकेशन, जियोकोडिंग, और jQuery के वादे : "तब नियंत्रण तर्क बहुत अच्छी तरह से पढ़ता है:" $(function () { $.when(getPosition()) .pipe(lookupCountry) .then(displayResults); }); "ध्यान दें कि पाइप अलग है फिर क्योंकि पाइप एक नया वादा वापस देता है। "
हिप्पिट्रैएल

5

वास्तव में यह पता चला है कि बीच का अंतर .then()और .pipe()अनावश्यक समझा जाता है और वे jQuery संस्करण 1.8 के रूप में ही हो बनाया गया है।

से द्वारा एक टिप्पणीjaubourg jQuery के बग ट्रैकर में टिकट # 11010 "बनाने DEFERRED.THEN == DEFERRED.PIPE की तरह वादा / ए ':

1.8 में, हम पुराने को हटा देंगे और इसे वर्तमान पाइप से बदल देंगे। लेकिन बहुत दुखद परिणाम यह है कि हमें लोगों को गैर-मानक, असफल और प्रगति का उपयोग करने के लिए कहना होगा, क्योंकि प्रस्ताव सरल, प्रभावी, केवल कॉलबैक जोड़ने का मतलब नहीं प्रदान करता है।

(जोर मेरा)


1
अब तक का सबसे अच्छा संदर्भ, मैं उन्नत उपयोगों की तलाश में हूं।
ट्वीस्टरेब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.