.Each () पूर्ण होने के बाद jQuery फ़ंक्शन को आमंत्रित करना


183

JQuery में, यह संभव है कि एक कॉलबैक आह्वान या घटना ट्रिगर की एक मंगलाचरण के बाद .each()(या पुनरावृत्ति कॉलबैक के किसी भी अन्य प्रकार) है पूरा

उदाहरण के लिए, मैं इसे "फीका और हटाना" पूरा करना चाहूंगा

$(parentSelect).nextAll().fadeOut(200, function() {
    $(this).remove();
});

कुछ गणना करने से पहले और के बाद नए तत्वों को सम्मिलित करना $(parentSelect)। मेरी गणना गलत है अगर मौजूदा तत्व अभी भी jQuery के लिए दिखाई दे रहे हैं और सोने में देरी कर रहे हैं / समय की कुछ मनमानी राशि (प्रत्येक तत्व के लिए 200) सबसे अच्छा भंगुर समाधान की तरह लगता है।

मैं .bind()एक इवेंट कॉलबैक के लिए आवश्यक तर्क आसानी से दे सकता हूं, लेकिन मुझे यकीन नहीं है कि .trigger()उपरोक्त पुनरावृत्ति पूरा होने के बाद सफाई कैसे करें । जाहिर है, मैं इसे ट्रिगर के अंदर ट्रिगर नहीं कर सकता क्योंकि यह कई बार आग लगाएगा।

के मामले में $.each(), मैंने डेटा तर्क के अंत में कुछ जोड़ने पर विचार किया है (कि मैं मैन्युअल रूप से पुनरावृत्ति निकाय की तलाश करूँगा), लेकिन मुझे उससे मजबूर होना पड़ेगा, इसलिए मुझे उम्मीद थी कि कोई और सुरुचिपूर्ण था पुनरावृति कॉलबैक के संबंध में प्रवाह को नियंत्रित करने का तरीका।


1
क्या मैं सही ढंग से समझता हूं कि यह इतना "" .each () "" नहीं है जिसे आप समाप्त करना चाहते हैं, बल्कि ".each ()" कॉल द्वारा लॉन्च किए गए सभी एनिमेशन हैं?
प्वांइट

यह एक अच्छी बात है। इस विशेष प्रश्न के साथ, हाँ, मैं मुख्य रूप से ".each ()" के पूरा होने के बारे में चिंतित हूं ... लेकिन मुझे लगता है कि आप एक और व्यवहार्य प्रश्न उठाते हैं।
लूथर बेकर

जवाबों:


161

@ टीवी के जवाब का एक विकल्प:

var elems = $(parentSelect).nextAll(), count = elems.length;

elems.each( function(i) {
  $(this).fadeOut(200, function() { 
    $(this).remove(); 
    if (!--count) doMyThing();
  });
});

ध्यान दें कि .each()स्वयं सिंक्रोनस है - कॉल का अनुसरण करने वाला विवरण कॉल पूरा .each()होने के बाद ही निष्पादित किया जाएगा .each()। हालांकि, पुनरावृति में शुरू किए गए अतुल्यकालिक संचालन .each()अपने तरीके से जारी रहेंगे। यहां यह मुद्दा है: तत्वों को फीका करने के लिए कॉल टाइमर-चालित एनिमेशन हैं, और जो अपनी गति से जारी हैं।

इसलिए, उपरोक्त समाधान, इस बात पर नज़र रखता है कि कितने तत्व फीके हो रहे हैं। प्रत्येक कॉल को .fadeOut()पूर्ण कॉलबैक मिलता है। जब कॉलबैक नोटिस में शामिल सभी मूल तत्वों के माध्यम से गिना जाता है, तो कुछ बाद की कार्रवाई को विश्वास के साथ लिया जा सकता है कि सभी लुप्त होती समाप्त हो गए हैं।

यह चार-वर्षीय उत्तर (2014 में इस बिंदु पर) है। ऐसा करने का एक आधुनिक तरीका शायद Deferred / Promise तंत्र का उपयोग करना शामिल है, हालांकि उपरोक्त सरल है और बस ठीक काम करना चाहिए।


4
मुझे यह बदलाव पसंद है, हालाँकि मैं तुलनात्मक नकारात्मकता के बजाय 0 से तुलना करूँगा (--count == 0) क्योंकि आप नीचे गिन रहे हैं। मेरे लिए यह इरादे को स्पष्ट करता है, हालांकि इसका एक ही प्रभाव है।
tvanfosson

जैसा कि यह पता चला है, प्रश्न पर आपकी प्रारंभिक टिप्पणी हाजिर थी। मैं .each () के बारे में पूछ रहा था और सोचा कि मैं वही चाहता हूं, लेकिन जैसा कि आप और तवानफोसन और अब पैट्रिक ने बताया है - यह अंतिम फीका था कि मुझे वास्तव में दिलचस्पी थी। मुझे लगता है कि हम सभी सहमत हैं कि आपका उदाहरण (गिनती के बजाय गिनती) अनुक्रमित) शायद सबसे सुरक्षित है।
लूथर बेकर

@ A.DIMO का क्या मतलब है, "बहुत जटिल"? क्या हिस्सा जटिल है?
नुकीले

169

शायद देर हो गई है लेकिन मुझे लगता है कि यह कोड काम करता है ...

$blocks.each(function(i, elm) {
 $(elm).fadeOut(200, function() {
  $(elm).remove();
 });
}).promise().done( function(){ alert("All was done"); } );

156

ठीक है, यह इस तथ्य के बाद थोड़ा हो सकता है, लेकिन .promise () को यह भी हासिल करना चाहिए कि आप क्या कर रहे हैं।

प्रलेखन का वादा

मैं इस परियोजना पर काम कर रहा हूं:

$( '.panel' )
    .fadeOut( 'slow')
    .promise()
    .done( function() {
        $( '#' + target_panel ).fadeIn( 'slow', function() {});
    });

:)


7
.promise () .each () पर उपलब्ध नहीं है
माइकल ज्वर

25

जावास्क्रिप्ट समकालिक रूप से चलता है, इसलिए जो कुछ भी आपके पास है वह पूरा each()होने तक नहीं चलेगा each()

निम्नलिखित परीक्षण पर विचार करें:

var count = 0;
var array = [];

// populate an array with 1,000,000 entries
for(var i = 0; i < 1000000; i++) {
    array.push(i);
}

// use each to iterate over the array, incrementing count each time
$.each(array, function() {
    count++
});

// the alert won't get called until the 'each' is done
//      as evidenced by the value of count
alert(count);

जब अलर्ट कहा जाता है, तो गिनती 1000000 के बराबर होगी क्योंकि चेतावनी तब तक नहीं चलेगी जब तक each()कि ऐसा नहीं किया जाता है।


8
दिए गए उदाहरण में समस्या यह है कि fadeOut को एनीमेशन कतार में रखा जाता है और समकालिक रूप से निष्पादित नहीं होता है। यदि आप eachप्रत्येक एनीमेशन का अलग-अलग उपयोग करते हैं और अलग-अलग शेड्यूल करते हैं, तो भी आपको एनीमेशन के बाद ईवेंट को फायर करना होगा, प्रत्येक फिनिश को नहीं।
tvanfosson

3
@tvanfosson - हाँ, मुझे पता है। लूथर जो पूरा करना चाहता है, उसके अनुसार आपका समाधान (और पॉइंटी का) सही दृष्टिकोण की तरह लगता है। लेकिन लूथर की टिप्पणियों से जैसे ... Naively, मैं कुछ ऐसी चीज़ों की तलाश कर रहा हूँ जैसे कि एलम्स (चिडिय़ाघर, बार) जहाँ foo = 'फंक्शन प्रत्येक तत्व पर लागू होता है' और बार = 'कॉलबैक पूरा होने के बाद कॉलबैक'। ... वह आग्रह करता है कि यह एक each()मुद्दा है। इसलिए मैंने इस उत्तर को मिश्रण में फेंक दिया।
user113716

आप सही पैट्रिक हैं। मैंने (गलत) समझ लिया था कि .each () मेरे कॉलबैक को शेड्यूल या पंक्तिबद्ध कर रहा था। मुझे लगता है कि fadeOut को लागू करना अप्रत्यक्ष रूप से मुझे उस नतीजे पर पहुंचा रहा था। tvanfosson और Pointy दोनों ने फ़ेडऑट समस्या के लिए उत्तर प्रदान किया है (जो कि मैं वास्तव में उसके बाद था) लेकिन आपकी पोस्ट वास्तव में मेरी समझ को थोड़ा ठीक करती है। आपका उत्तर वास्तव में मूल प्रश्न का सबसे अच्छा उत्तर देता है, जैसा कि इंगित किया गया है, जबकि Pointy और tvanfosson ने उस प्रश्न का उत्तर दिया जो मैं पूछने की कोशिश कर रहा था। काश मैं दो उत्तर चुन पाता। इस उत्तर को 'मिश्रण में फेंकने' के लिए धन्यवाद :)
लूथर बेकर

@ user113716 मुझे लगा कि अंदर काम eachकरने की गारंटी नहीं दी जाती है alert। क्या आप मुझे इस पर पढ़ने के लिए समझा या बता सकते हैं?
मैकीज जानकोव्स्की

5

मुझे सरणियों से निपटने के लिए बहुत सी प्रतिक्रियाएं मिलीं, लेकिन एक जेन्स ऑब्जेक्ट के साथ नहीं। मेरा समाधान बस एक बार काउंटर को बढ़ाने के दौरान ऑब्जेक्ट के माध्यम से पुनरावृत्त करना था और फिर जब आपके कोड को निष्पादित करने के लिए ऑब्जेक्ट के माध्यम से पुनरावृत्ति करता है तो आप एक दूसरे काउंटर को बढ़ा सकते हैं। फिर आप बस दो काउंटरों की एक साथ तुलना करें और अपना समाधान प्राप्त करें। मुझे पता है कि यह थोड़ा सांवला है, लेकिन मुझे अब तक अधिक सुरुचिपूर्ण समाधान नहीं मिला है। यह मेरा उदाहरण कोड है:

var flag1 = flag2 = 0;

$.each( object, function ( i, v ) { flag1++; });

$.each( object, function ( ky, val ) {

     /*
        Your code here
     */
     flag2++;
});

if(flag1 === flag2) {
   your function to call at the end of the iteration
}

जैसा मैंने कहा, यह सबसे सुरुचिपूर्ण नहीं है, लेकिन यह काम करता है और यह अच्छी तरह से काम करता है और मुझे अभी तक बेहतर समाधान नहीं मिला है।

चीयर्स, जेपी


1
नहीं, यह काम नहीं करता है। यह सभी ब्लीच की आग और फिर अंतिम चीज और एक ही समय में सब कुछ चलाता है। अपने .each पर सेटटाइमआउट डालने का प्रयास करें और आप देखेंगे कि यह फ़ौरन फ्लैग 1 === फ्लैग 2 को तुरंत चलाएगा
माइकल फीवर

1

यदि आप इसे एक-दो चरणों में तैयार करना चाहते हैं, तो यह काम कर सकता है। यह आदेश में परिष्करण एनिमेशन पर निर्भर है, हालांकि। मुझे नहीं लगता कि यह एक समस्या होनी चाहिए।

var elems = $(parentSelect).nextAll();
var lastID = elems.length - 1;

elems.each( function(i) {
    $(this).fadeOut(200, function() { 
        $(this).remove(); 
        if (i == lastID) {
           doMyThing();
        }
    });
});

यह काम करेगा - हालांकि, वह नहीं जो मैंने आशा की थी। Naively, मैं कुछ एलम्स.चू (foo, bar) की तरह देख रहा हूँ, जहाँ foo = 'फंक्शन प्रत्येक तत्व पर लागू होता है' और सभी पुनरावृत्तियों के पूरा होने के बाद बार = 'कॉलबैक'। मैं इस सवाल को थोड़ा और समय दूंगा कि क्या हम jQuery के किसी अंधेरे कोने में आते हैं :)
लूथर बेकर

AFAIK - आपको इसे "अंतिम" एनीमेशन पूरा होने पर ट्रिगर करना होगा और चूंकि वे अतुल्यकालिक रूप से चलते हैं, इसलिए आपको इसे एनीमेशन कॉलबैक में करना होगा। मुझे @ Ptyty का संस्करण पसंद है, जो मैंने बेहतर लिखा है क्योंकि इसमें ऑर्डरिंग पर निर्भरता नहीं है, ऐसा नहीं है कि मुझे लगता है कि यह एक समस्या होगी।
tvanfosson

0

किस बारे में

$(parentSelect).nextAll().fadeOut(200, function() { 
    $(this).remove(); 
}).one(function(){
    myfunction();
}); 

यह निश्चित रूप से एक बार myfunction () का आह्वान करता है (और मुझे एक और jQuery अवधारणा से परिचित कराता है), लेकिन जो मैं देख रहा था, वह 'जब' की गारंटी थी, तो यह चलेगा - केवल यह नहीं कि यह एक बार चलेगा। और, जैसा कि पैट्रिक उल्लेख करता है, वह हिस्सा बहुत आसान हो जाता है। मैं वास्तव में जिस चीज की तलाश कर रहा था वह अंतिम फीका तर्क के चलने के बाद कुछ आह्वान करने का एक तरीका था, जो मुझे नहीं लगता है। कोई () गारंटी देता है।
लूथर बेकर

मुझे लगता है कि श्रृंखला ऐसा करती है - चूंकि पहला भाग अंतिम भाग से पहले चलता है।
मार्क शुल्त्स

0

आपको काम करने के लिए अपने बाकी अनुरोधों की कतार लगानी होगी।

var elems = $(parentSelect).nextAll();
var lastID = elems.length - 1;

elems.each( function(i) {
    $(this).fadeOut(200, function() { 
        $(this).remove(); 
        if (i == lastID) {
            $j(this).queue("fx",function(){ doMyThing;});
        }
    });
});

0

मैं एक ही समस्या से मिलता हूं और मैंने निम्नलिखित कोड जैसे समाधान के साथ हल किया है:

var drfs = new Array();
var external = $.Deferred();
drfs.push(external.promise());

$('itemSelector').each( function() {
    //initialize the context for each cycle
    var t = this; // optional
    var internal = $.Deferred();

    // after the previous deferred operation has been resolved
    drfs.pop().then( function() {

        // do stuff of the cycle, optionally using t as this
        var result; //boolean set by the stuff

        if ( result ) {
            internal.resolve();
        } else {
            internal.reject();
        }
    }
    drfs.push(internal.promise());
});

external.resolve("done");

$.when(drfs).then( function() {
    // after all each are resolved

});

समाधान निम्न समस्या को हल करता है: डीईएफ़्रेड ऑब्जेक्ट का उपयोग करके इन (।) पुनरावृत्ति में शुरू किए गए अतुल्यकालिक संचालन को सिंक्रनाइज़ करने के लिए।


आप पहले एक समापन ब्रैकेट को याद कर रहे हैं: drfs.push (internal.promise ()); कम से कम मुझे इसके पहले लगता है ..
माइकल फीवर

0

शायद देर से प्रतिक्रिया लेकिन इस https://github.com/ACFBentveld/Await को संभालने के लिए एक पैकेज है

 var myObject = { // or your array
        1 : 'My first item',
        2 : 'My second item',
        3 : 'My third item'
    }

    Await.each(myObject, function(key, value){
         //your logic here
    });

    Await.done(function(){
        console.log('The loop is completely done');
    });

0

मैं कुछ इस तरह का उपयोग कर रहा हूँ:

$.when(
           $.each(yourArray, function (key, value) {
                // Do Something in loop here
            })
          ).then(function () {
               // After loop ends.
          });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.