पिछले फ़ंक्शन के पूरा होने के बाद किसी फ़ंक्शन को कॉल करें


179

मेरे पास निम्नलिखित जावास्क्रिप्ट कोड है:

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable);
        function2(someOtherVariable);
    }
    else {
        doThis(someVariable);
    }
});

मैं यह कैसे सुनिश्चित कर सकता हूं कि पूरा function2होने के बाद ही इसे कहा function1जाए?


24
है function1एक async कार्रवाई करते?
LiraNuna

8
येड्स, यदि फ़ंक्शन 1 में एनिमेशन हैं, फ़ंक्शन 2 को निष्पादित किया जाएगा, जबकि फ़ंक्शन 1 के एनिमेशन अभी भी हो रहे हैं। फ़ंक्शन 1 में सब कुछ पूरी तरह से शुरू होने तक आप फ़ंक्शन 2 प्रतीक्षा कैसे करेंगे?
trusktr

क्या कोई मुझे समझा सकता है कि फ़ंक्शन 1 को पूरा होने तक फ़ंक्शन 2 को सुनिश्चित करने के लिए कुछ भी करने की आवश्यकता क्यों है? यहाँ कोई अतुल्यकालिक ऑपरेशन नहीं हो रहा है इसलिए function2 तब तक नहीं चलेगा जब तक function1 पूरा नहीं हो जाता क्योंकि यह ऑपरेशन सिंक्रोनस है।
आरोन

जवाबों:


206

एक अनाम कॉलबैक निर्दिष्ट करें, और फ़ंक्शन 1 को स्वीकार करें:

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable, function() {
          function2(someOtherVariable);
        });
    }
    else {
        doThis(someVariable);
    }
});


function function1(param, callback) {
  ...do stuff
  callback();
} 

11
+1 लेकिन यदि वह 1.5 का उपयोग कर रहा है, तो वह नए
Deferreds

त्वरित प्रतिक्रिया के लिए धन्यवाद)। हां, फ़ंक्शन 1 केवल एक सरल अतुल्यकालिक कार्य कर रहा है, इसलिए मेरा मानना ​​है कि आप इसमें सही हैं कि मुझे कॉलबैक बनाना होगा - या इस आस्थगित व्यवसाय पर एक नज़र डालें जिसका जिक्र डर्विंकल ने किया है। धन्यवाद फिर से, दोस्तों। मैं कुछ नींद लेने जा रहा हूं, और सुबह फिर से निपटूंगा।
र्र्ररयायणं

13
यह उत्तर समाधान नहीं है। यहाँ सबूत है कि यह काम नहीं करता है: jsfiddle.net/trusktr/M2h6e
trusktr

12
@MikeRobinson यहाँ समस्या है: क्या होगा अगर ...do stuffऐसी चीजें शामिल हैं जो अतुल्यकालिक हैं? जब अपेक्षित होगा तब भी फंक्शन 2 फायर नहीं करेगा। ऊपर मेरी टिप्पणी में उदाहरण से पता चलता है कि क्योंकि foo()फ़ंक्शन में अतुल्यकालिक कोड है, इसलिए यह bar()आग नहीं लगाता है कि foo()सामग्री को निष्पादित करने के $.when().then()बाद भी, उन्हें एक के बाद एक कॉल करने के लिए उपयोग किया जाता है । यह उत्तर केवल मान्य है (और यदि केवल) तो ...do stuffआपके कोड का सारा सामान सख्ती से समकालिक है।
त्रिकुट्र

1
@trusktr उस स्थिति में आपको एसिंक्रोनस कॉल के n वें स्तर तक पहले कॉलबैक को पास करते रहना होगा , फिर callBack()सभी n एसिंक्रोनस कॉल करने के बाद फायर करें । चूंकि ओपी ने उल्लेख नहीं किया है कि वह इस कार्य में क्या कर रहा है, इसलिए इसे एक स्तर की अतुल्यकालिक कॉल मान लिया।
GoodSp33d

96

यदि आप jQuery 1.5 का उपयोग कर रहे हैं, तो आप नए Deferreds पैटर्न का उपयोग कर सकते हैं:

$('a.button').click(function(){
    if(condition == 'true'){
        $.when(function1()).then(function2());
    }
    else {
        doThis(someVariable);
    }
});

संपादित करें: अपडेटेड ब्लॉग लिंक:

रेबेका मर्फी ने इस पर एक महान लेखन किया था: http://rmurphey.com/blog/2010/12/25/deferreds-coming-to-jquery/


2
लेकिन क्या यह एक काम करने वाला उदाहरण है? क्या टाल दिया जा रहा है? आप तुरंत फ़ंक्शन 1 और फ़ंक्शन 2 को निष्पादित कर रहे हैं। (मैं मूल टिप्पणीकार नहीं हूँ।)
user113716

10
वह मेरे लिए बिल्कुल भी काम नहीं कर रहा है। फ़ंक्शन 1 और फ़ंक्शन 2 दोनों बिल्कुल एक ही समय में निष्पादित होते हैं (मानव आंख द्वारा अवलोकन के रूप में)। यहाँ इसका छोटा उदाहरण है: jsfiddle.net/trusktr/M2h6e
trusktr

1
रेबेका मर्फी का लेखन इससे पहले था कि डेफ़र्ड्स को jQuery से परिचित कराया गया था और यह इस बात पर आधारित उदाहरणों का उपयोग करता है कि लेखक को कैसे लगता है कि इसे लागू किया जाएगा। कृपया jQuery की साइट पर जाएं यह देखने के लिए कि वास्तव में इस सुविधा का उपयोग कैसे करें: api.jquery.com/jQuery.Deferred
स्पेन्सर विलियम्स

1
यहां तक ​​कि jQuery 1.5 या कुछ आधुनिक के साथ, आप नहीं चाहते हैं $.when(function1).then(function2);(बिना कोष्ठक के जो फ़ंक्शन कहते हैं)?
तेईपेमम

1
इन टिप्पणियों को कुछ साल देर से पढ़ना। function1एक वादा वापस करना चाहिए। उस मामले में इसे वास्तविक निष्पादित कार्य होना चाहिए, संदर्भ नहीं। जब resolveउस वादे पर बुलाया जाता है तो function2उसे निष्पादित किया जाता है। यह आसानी से समझा जाता है कि function1एक अजाक्स कॉल है। doneकॉलबैक तो वादा हल होगा। मुझे उम्मीद है कि यह स्पष्ट है।
१६'१४

46

इसे इस्तेमाल करे :

function method1(){
   // some code

}

function method2(){
   // some code
}

$.ajax({
   url:method1(),
   success:function(){
   method2();
}
})

37

यह उत्तर मानक promisesकी एक जावास्क्रिप्ट सुविधा का उपयोग करता है ECMAScript 6। यदि आपका लक्ष्य प्लेटफ़ॉर्म समर्थन नहीं करता है promises, तो उसे PromiseJs के साथ पॉलीफ़िल करें

जावास्क्रिप्ट में अतुल्यकालिक संचालन को संभालने के लिए वादे एक नया (और बहुत बेहतर) तरीका है:

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable).then(function() {
            //this function is executed after function1
            function2(someOtherVariable);
        });
    }
    else {
        doThis(someVariable);
    }
});


function function1(param, callback) {
    return new Promise(function (fulfill, reject){
        //do stuff
        fulfill(result); //if the action succeeded
        reject(error); //if the action did not succeed
    });
} 

यह इस सरल उदाहरण के लिए एक महत्वपूर्ण ओवरहेड की तरह लग सकता है, लेकिन अधिक जटिल कोड के लिए यह कॉलबैक का उपयोग करने से कहीं बेहतर है। आप कई thenबयानों का उपयोग करके आसानी से कई अतुल्यकालिक कॉल को चेन कर सकते हैं :

function1(someVariable).then(function() {
    function2(someOtherVariable);
}).then(function() {
    function3();
});

आप आसानी से jQuery deferrds को भी लपेट सकते हैं (जो $.ajaxकॉल से वापस आ जाते हैं):

Promise.resolve($.ajax(...params...)).then(function(result) {
    //whatever you want to do after the request
});

जैसा कि @charlietfl ने उल्लेख किया है, jqXHRऑब्जेक्ट इंटरफ़ेस को $.ajax()लागू करता Promiseहै। तो यह वास्तव में इसे में लपेटने के लिए आवश्यक नहीं है Promise, इसे सीधे इस्तेमाल किया जा सकता है:

$.ajax(...params...).then(function(result) {
    //whatever you want to do after the request
});

Promise.resolveरैपिंग $.ajaxविरोधी पैटर्न है क्योंकि $.ajaxरिटर्न का वादा करने योग्य वादा
charlietfl

@charlietfl लेकिन यह वास्तविक नहीं है Promise, यह सिर्फ इंटरफ़ेस को लागू करता है। मैं यह यकीन है कि कैसे नहीं व्यवहार करने के तरीके कोई वास्तविक गुजर कर रहा हूँ Promiseइसके लिए thenविधि, या क्या एक Promise.allएक अगर करना होगा jqXHRऔर एक Promiseयह करने के लिए पारित कर रहे हैं। उसके लिए मुझे और परीक्षण करने की आवश्यकता है। लेकिन संकेत के लिए धन्यवाद, मैं इसे उत्तर में जोड़ूंगा!
डोमेसे

वास्तव में jQuery के संस्करण 3+ में वादा ए + अनुपालन है। बावजूद $.ajax.thenनई बात नहीं है
charlietfl

21

या आप एक समारोह पूरा होने पर एक कस्टम इवेंट को ट्रिगर कर सकते हैं, फिर इसे दस्तावेज़ में बाँध सकते हैं:

function a() {
    // first function code here
    $(document).trigger('function_a_complete');
}

function b() {
    // second function code here
}

$(document).bind('function_a_complete', b);

इस पद्धति का उपयोग करते हुए, फ़ंक्शन 'बी' केवल AFTER फ़ंक्शन 'a' को निष्पादित कर सकता है, क्योंकि ट्रिगर केवल तभी मौजूद होता है जब फ़ंक्शन निष्पादित होता है।


"JQuery 1.7 के रूप में, .on () विधि ईवेंट हैंडलर को दस्तावेज़ में संलग्न करने के लिए पसंदीदा तरीका है।" api.jquery.com/bind
CodeVirtuoso


3

यह इस बात पर निर्भर करता है कि function1 क्या कर रहा है।

यदि फ़ंक्शन 1 कुछ सरल सिनक्रॉउंस जावास्क्रिप्ट कर रहा है, जैसे कि डिव वैल्यू या कुछ और अपडेट करने के लिए, तो फ़ंक्शन 2 पूरा होने के बाद फ़ंक्शन 2 फायर करेगा।

यदि फ़ंक्शन 1 एक एसिंक्रोनस कॉल कर रहा है, जैसे कि AJAX कॉल, तो आपको एक "कॉलबैक" विधि (अधिकांश AJAX एपीआई के कॉलबैक फ़ंक्शन पैरामीटर है) बनाने की आवश्यकता होगी। फिर कॉलबैक में function2 को कॉल करें। उदाहरण के लिए:

function1()
{
  new AjaxCall(ajaxOptions, MyCallback);
}

function MyCallback(result)
{
  function2(result);
}

2

यदि विधि 1 को विधि 2, 3, 4 के बाद निष्पादित किया जाना है, तो निम्न कोड स्निपेट जावास्क्रिप्ट में आस्थगित वस्तु का उपयोग करके इसके लिए समाधान हो सकता है।

function method1(){
  var dfd = new $.Deferred();
     setTimeout(function(){
     console.log("Inside Method - 1"); 
     method2(dfd);	 
    }, 5000);
  return dfd.promise();
}

function method2(dfd){
  setTimeout(function(){
   console.log("Inside Method - 2"); 
   method3(dfd);	
  }, 3000);
}

function method3(dfd){
  setTimeout(function(){
   console.log("Inside Method - 3"); 	
   dfd.resolve();
  }, 3000);
}

function method4(){   
   console.log("Inside Method - 4"); 	
}

var call = method1();

$.when(call).then(function(cb){
  method4();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


0

यदि फ़ंक्शन 1 कुछ सिंक फ़ंक्शन है जिसे आप एक एसिंक्स एक में बदलना चाहते हैं क्योंकि इसे पूरा होने में कुछ समय लगता है, और कॉलबैक जोड़ने के लिए आपके पास इस पर कोई नियंत्रण नहीं है:

function function1 (someVariable) {
    var date = Date.now ();
    while (Date.now () - date < 2000);      // function1 takes some time to complete
    console.log (someVariable);
}
function function2 (someVariable) {
    console.log (someVariable);
}
function onClick () {
    window.setTimeout (() => { function1 ("This is function1"); }, 0);
    window.setTimeout (() => { function2 ("This is function2"); }, 0);
    console.log ("Click handled");  // To show that the function will return before both functions are executed
}
onClick ();

उत्पादन होगा:

Click handled

... और 2 सेकंड के बाद:

This is function 1
This is function 2

यह काम करता है क्योंकि कॉलिंग window.setTimeout () जेएस रनटाइन टास्क लूप में एक कार्य जोड़ देगा, जो कि एक एसिंक्स कॉल करता है, और क्योंकि जेएस रनटाइम के "रन-टू-पूरा" का मूल सिद्धांत यह सुनिश्चित करता है कि ऑनक्लिक () समाप्त होने से पहले कभी बाधित नहीं होता है।

ध्यान दें कि यह उतना ही मज़ेदार है क्योंकि इसे समझना मुश्किल कोड हो सकता है ...

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