एक के बाद एक उन्हें निष्पादित करने के लिए मुझे 3 कार्यों को कैसे कॉल करना चाहिए?


151

अगर मुझे एक के बाद एक इस फ़ंक्शन की आवश्यकता है,

$('#art1').animate({'width':'1000px'},1000);        
$('#art2').animate({'width':'1000px'},1000);        
$('#art3').animate({'width':'1000px'},1000);        

मुझे पता है jQuery में मैं कुछ ऐसा कर सकता था:

$('#art1').animate({'width':'1000px'},1000,'linear',function(){
    $('#art2').animate({'width':'1000px'},1000,'linear',function(){
        $('#art3').animate({'width':'1000px'},1000);        
    });        
});        

लेकिन, मान लें कि मैं jQuery का उपयोग नहीं कर रहा हूं और मैं कॉल करना चाहता हूं:

some_3secs_function(some_value);        
some_5secs_function(some_value);        
some_8secs_function(some_value);        

निष्पादित करने के लिए मुझे इस फ़ंक्शन को कैसे कॉल करना चाहिए some_3secs_function, और कॉल को समाप्त करने के some_5secs_functionबाद , फिर निष्पादित करें और उस कॉल को समाप्त करने के बाद कॉल करें some_8secs_function?

अपडेट करें:

यह अभी भी काम नहीं कर रहा है:

(function(callback){
    $('#art1').animate({'width':'1000px'},1000);
    callback();
})((function(callback2){
    $('#art2').animate({'width':'1000px'},1000);
    callback2();
})(function(){
    $('#art3').animate({'width':'1000px'},1000);
}));

एक ही समय में तीन एनिमेशन शुरू होते हैं

मेरी गलती कहाँ है?


क्या आपका मतलब है कि कार्यों को 3 5 और 8 सेकंड में बुलाया जाए या एक के बाद एक?
ट्रैस वासटन

मुझे लगता है कि आप सिंक्रोनस बनाम अतुल्यकालिक फ़ंक्शन निष्पादन के बारे में अनिश्चित हैं। मैंने नीचे अपना जवाब अपडेट किया है। आशा करता हूँ की ये काम करेगा।
वेन

यह कोशिश करो .. github.com/dineshkani24/queuecall
दिनेशकी

जवाबों:


243

जावास्क्रिप्ट में, सिंक्रोनस और एसिंक्रोनस फ़ंक्शन होते हैं।

तुल्यकालिक कार्य

जावास्क्रिप्ट में अधिकांश फ़ंक्शन सिंक्रोनस हैं। यदि आप एक पंक्ति में कई तुल्यकालिक कार्यों को कॉल करने के लिए थे

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

वे क्रम में निष्पादित करेंगे। पूरा doSomethingElseहोने तक शुरू नहीं होगा doSomethingdoSomethingUsefulThisTime, बदले में, doSomethingElseपूरा होने तक शुरू नहीं होगा ।

अतुल्यकालिक कार्य

अतुल्यकालिक समारोह, हालांकि, एक दूसरे के लिए इंतजार नहीं करेंगे। हमें उसी कोड नमूने को देखें जो हमारे पास था, इस बार यह मानते हुए कि फ़ंक्शन अतुल्यकालिक हैं

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

कार्यों को क्रम में शुरू किया जाएगा, लेकिन वे सभी एक ही समय में लगभग निष्पादित करेंगे। आप लगातार यह अनुमान नहीं लगा सकते हैं कि कौन सा व्यक्ति सबसे पहले समाप्त होगा: वह जो निष्पादित करने के लिए सबसे कम समय लेता है वह सबसे पहले समाप्त होगा।

लेकिन कभी-कभी, आप ऐसे कार्यों को चाहते हैं जो क्रम में निष्पादित करने के लिए अतुल्यकालिक हैं, और कभी-कभी आप ऐसे कार्यों को चाहते हैं जो अतुल्यकालिक रूप से निष्पादित करने के लिए तुल्यकालिक हैं। सौभाग्य से, क्रमशः कॉलबैक और टाइमआउट के साथ यह संभव है।

कॉलबैक

मान लेते हैं कि हमारे पास तीन अतुल्यकालिक कार्य हैं जिन्हें हम क्रम , और some_3secs_function, में निष्पादित करना चाहते हैं ।some_5secs_functionsome_8secs_function

चूंकि फ़ंक्शन जावास्क्रिप्ट में तर्क के रूप में पारित किए जा सकते हैं, आप फ़ंक्शन को पूरा होने के बाद निष्पादित करने के लिए कॉलबैक के रूप में एक फ़ंक्शन पास कर सकते हैं।

यदि हम इस तरह के कार्य बनाते हैं

function some_3secs_function(value, callback){
  //do stuff
  callback();
}

तब आप इस तरह से फिर कॉल कर सकते हैं:

some_3secs_function(some_value, function() {
  some_5secs_function(other_value, function() {
    some_8secs_function(third_value, function() {
      //All three functions have completed, in order.
    });
  });
});

समय समाप्ति

जावास्क्रिप्ट में, आप एक निश्चित समय के बाद (मिलीसेकंड में) निष्पादित करने के लिए एक फ़ंक्शन बता सकते हैं। यह, प्रभाव में, तुल्यकालिक कार्यों को अतुल्यकालिक रूप से व्यवहार कर सकता है।

यदि हमारे पास तीन सिंक्रोनस फ़ंक्शन हैं, तो हम setTimeoutफ़ंक्शन का उपयोग करके उन्हें एसिंक्रोनस रूप से निष्पादित कर सकते हैं ।

setTimeout(doSomething, 10);
setTimeout(doSomethingElse, 10);
setTimeout(doSomethingUsefulThisTime, 10);

यह, हालांकि, थोड़ा बदसूरत है और DRY सिद्धांत [विकिपीडिया] का उल्लंघन करता है । हम फ़ंक्शन की एक सरणी और एक टाइमआउट स्वीकार करता है, जो एक समारोह बनाकर इसे थोड़ा साफ कर सकता है।

function executeAsynchronously(functions, timeout) {
  for(var i = 0; i < functions.length; i++) {
    setTimeout(functions[i], timeout);
  }
}

इसे इस तरह कहा जा सकता है:

executeAsynchronously(
    [doSomething, doSomethingElse, doSomethingUsefulThisTime], 10);

सारांश में, यदि आपके पास एसिंक्रोनस फ़ंक्शन हैं जो आप सिंक्रोनाइज़ करना चाहते हैं, तो कॉलबैक का उपयोग करें, और यदि आपके पास सिंक्रोनस फ़ंक्शन हैं जो आप एसिंक्रोनस रूप से निष्पादित करना चाहते हैं, तो टाइमआउट का उपयोग करें।


7
यह 3,5 और 8 सेकंड के कार्यों में देरी नहीं करेगा, जैसा कि उदाहरण द्वारा सुझाया गया है, वे बस एक के बाद एक चलाएंगे।
ट्रैस वासटन

1
@Peter - रुको, तो मैं उलझन में हूँ। यदि ये सरल समकालिक कॉल होते हैं जिन्हें पूरा होने में कुछ सेकंड लगते हैं, तो हमें इसकी कोई आवश्यकता क्यों है?
वेन

9
@Peter - सबसे सुंदर, जटिल विधि के लिए +1 मैंने कभी क्रम में तीन सिंक्रोनस फ़ंक्शन को कॉल करने के लिए देखा है।
वेन

4
Async और सिंक js फ़ंक्शन के बीच अंतर को स्पष्ट रूप से समझाने के लिए धन्यवाद। यह बहुत समझाता है।
जॉल्सन

2
यह निम्नलिखित कारणों के लिए सही नहीं है: (1) 3 टाइमआउट सभी 10 सेकंड के बाद हल हो जाएंगे, इसलिए सभी 3 लाइनें एक ही समय में ट्रिगर होती हैं। (2) इस विधि से आपको समय से पहले की अवधि जानने की आवश्यकता होती है और भविष्य में होने वाले "शेड्यूल" फ़ंक्शन को हल करने के लिए श्रृंखला में पहले के async कार्यों पर प्रतीक्षा करने और ट्रिगर होने के बजाय। --- इसके बजाय आप कॉलबैक, वादों, या एसिंक्स लाइब्रेरी का उपयोग करके निम्नलिखित में से किसी एक उत्तर का उपयोग करना चाहते हैं।
जीरोस्टिस्क

37

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

यदि आप एनिमेशन का उपयोग करना चाहते हैं तो किसी अन्य फ़ंक्शन को चलाने तक एनिमेशन के साथ एक फ़ंक्शन समाप्त होने तक प्रतीक्षा करें, यहां मेरे जवाब को देखें jQuery

यहाँ आपके कोड के साथ ES6 Promisesऔर कैसा दिखेगा jQuery animations

Promise.resolve($('#art1').animate({ 'width': '1000px' }, 1000).promise()).then(function(){
    return Promise.resolve($('#art2').animate({ 'width': '1000px' }, 1000).promise());
}).then(function(){
    return Promise.resolve($('#art3').animate({ 'width': '1000px' }, 1000).promise());
});

सामान्य तरीकों को भी लपेटा जा सकता है Promises

new Promise(function(fulfill, reject){
    //do something for 5 seconds
    fulfill(result);
}).then(function(result){
    return new Promise(function(fulfill, reject){
        //do something for 5 seconds
        fulfill(result);
    });
}).then(function(result){
    return new Promise(function(fulfill, reject){
        //do something for 8 seconds
        fulfill(result);
    });
}).then(function(result){
    //do something with the result
});

thenविधि ही के रूप में क्रियान्वित किया जाता है Promiseसमाप्त। आम तौर पर, functionउत्तीर्ण का रिटर्न मान thenपरिणाम के रूप में अगले एक को दिया जाता है।

लेकिन अगर कोई Promiseलौटाया जाता है, तो अगला thenकार्य Promiseसमाप्त होने तक प्रतीक्षा करता है और इसके परिणाम (उस मूल्य को पारित किया जाता है fulfill) प्राप्त करता है।


मुझे पता है कि यह उपयोगी है, लेकिन कोड को वास्तविक संदर्भ में खोजे बिना समझने के लिए दिया गया कोड कठिन लगता है। मुझे यह वीडियो YouTube पर मिला: youtube.com/watch?v=y5mltEaQxa0 - और वीडियो के स्रोत को यहां से लिखा है। drive.google.com/file/d/1NrsAYs1oaxXw0kv9hv7a6LjtOEb6x7z-/… कुछ और बारीकियां हैं जैसे कि गायब होना यह उदाहरण है कि यह विस्तृत है। (getPostById () लाइन में एक अलग आईडी का उपयोग करें या किसी लेखक का नाम बदलने की कोशिश करें ताकि यह किसी पोस्ट आदि से मेल न खाए)
JGFMK

20

ऐसा लगता है कि आप तुल्यकालिक और अतुल्यकालिक फ़ंक्शन निष्पादन के बीच के अंतर की पूरी तरह से सराहना नहीं कर रहे हैं ।

आपके द्वारा अपडेट में प्रदान किया गया कोड आपके प्रत्येक कॉलबैक फ़ंक्शन को तुरंत निष्पादित करता है, जो बदले में तुरंत एक एनीमेशन शुरू करता है। एनिमेशन, तथापि, पर अमल asyncronously । यह इस तरह काम करता है:

  1. एनीमेशन में एक कदम है
  2. setTimeoutअगले एनीमेशन कदम और एक देरी वाले एक समारोह के साथ कॉल करें
  3. कुछ समय बीत जाता है
  4. setTimeoutनिष्पादित करने के लिए दिया गया कॉलबैक
  5. चरण 1 पर वापस जाएं

यह तब तक जारी रहता है जब तक कि एनीमेशन में अंतिम चरण पूरा नहीं हो जाता। इस बीच, आपके समकालिक कार्य बहुत पहले पूरे हो चुके हैं। दूसरे शब्दों में, animateफ़ंक्शन पर आपका कॉल वास्तव में 3 सेकंड नहीं लेता है। प्रभाव देरी और कॉलबैक के साथ सिम्युलेटेड है।

आपको क्या चाहिए एक कतार । आंतरिक रूप से, jQuery के एनिमेशन को कतारबद्ध करता है, केवल इसी संबंधित एनीमेशन के पूरा होने पर आपके कॉलबैक को निष्पादित करता है । यदि आपका कॉलबैक फिर से एक और एनीमेशन शुरू करता है, तो प्रभाव यह है कि वे अनुक्रम में निष्पादित होते हैं।

सबसे सरल मामले में यह निम्नलिखित के बराबर है:

window.setTimeout(function() {
    alert("!");
    // set another timeout once the first completes
    window.setTimeout(function() {
        alert("!!");
    }, 1000);
}, 3000); // longer, but first

यहां एक सामान्य एसिंक्रोनस लूपिंग फ़ंक्शन है। यह दिए गए कार्यों को क्रम में कॉल करेगा, प्रत्येक के बीच सेकंड की निर्दिष्ट संख्या की प्रतीक्षा कर रहा है।

function loop() {
    var args = arguments;
    if (args.length <= 0)
        return;
    (function chain(i) {
        if (i >= args.length || typeof args[i] !== 'function')
            return;
        window.setTimeout(function() {
            args[i]();
            chain(i + 1);
        }, 2000);
    })(0);
}    

उपयोग:

loop(
  function() { alert("sam"); }, 
  function() { alert("sue"); });

आप इसे स्पष्ट रूप से कॉन्फ़िगर करने के लिए प्रतीक्षा समय लेने के लिए संशोधित कर सकते हैं या तुरंत पहले फ़ंक्शन को निष्पादित कर सकते हैं या निष्पादित कर सकते हैं या चेन रिटर्न में falseया applyनिर्दिष्ट संदर्भ में फ़ंक्शन के लिए या जो कुछ भी आपको आवश्यकता हो सकती है उसे निष्पादित करने से रोक सकते हैं।


14

मेरा मानना ​​है कि async लाइब्रेरी आपको ऐसा करने के लिए एक बहुत ही सुंदर तरीका प्रदान करेगी। हालांकि वादे और कॉलबैक के साथ जुगाड़ करने में थोड़ी मुश्किल हो सकती है, लेकिन async आपकी सोची हुई प्रक्रिया को कारगर बनाने के लिए साफ-सुथरा पैटर्न दे सकता है। सीरियल में फ़ंक्शंस चलाने के लिए, आपको उन्हें एक async झरने में डालना होगा । Async लिंगो में, प्रत्येक फ़ंक्शन को कहा जाता है taskजो कुछ तर्क लेता है और ए callback; जो अनुक्रम में अगला कार्य है। मूल संरचना कुछ इस तरह दिखाई देगी:

async.waterfall([
  // A list of functions
  function(callback){
      // Function no. 1 in sequence
      callback(null, arg);
  },
  function(arg, callback){
      // Function no. 2 in sequence
      callback(null);
  }
],    
function(err, results){
   // Optional final callback will get results for all prior functions
});

मैंने यहाँ संरचना की संक्षिप्त व्याख्या करने का प्रयास किया है। अधिक जानकारी के लिए झरना गाइड के माध्यम से पढ़ें , यह बहुत अच्छी तरह से लिखा गया है।


1
यह वास्तव में जेएस को थोड़ा और अधिक मजबूत बनाता है।
माइक

9

आपके कार्यों को कॉलबैक फ़ंक्शन लेना चाहिए, जिसे समाप्त होने पर कॉल किया जाता है।

function fone(callback){
...do something...
callback.apply(this,[]);

}

function ftwo(callback){
...do something...
callback.apply(this,[]);
}

तब उपयोग इस तरह होगा:

fone(function(){
  ftwo(function(){
   ..ftwo done...
  })
});

4
asec=1000; 

setTimeout('some_3secs_function("somevalue")',asec*3);
setTimeout('some_5secs_function("somevalue")',asec*5);
setTimeout('some_8secs_function("somevalue")',asec*8);

मैं यहां सेटटाइमआउट की गहन चर्चा में नहीं जाऊंगा, लेकिन:

  • इस मामले में मैंने एक स्ट्रिंग के रूप में निष्पादित करने के लिए कोड जोड़ा है। यह आपके सेटटाइम-एड फ़ंक्शन में एक var पास करने का सबसे सरल तरीका है, लेकिन शुद्धतावादी शिकायत करेंगे।
  • आप उद्धरणों के बिना एक फ़ंक्शन नाम भी पास कर सकते हैं, लेकिन कोई भी चर पारित नहीं किया जा सकता है।
  • आपका कोड ट्रिगर करने के लिए सेटटाइमआउट की प्रतीक्षा नहीं करता है।
  • यह पहली बार में आपके सिर को पाने के लिए कठिन हो सकता है: पिछले बिंदु के कारण, यदि आप अपने कॉलिंग फ़ंक्शन से एक वैरिएबल पास करते हैं, तो वह वेरिएबल उस समय तक मौजूद नहीं होगा जब टाइमआउट ट्रिगर होता है - कॉलिंग फ़ंक्शन निष्पादित हो जाएगा और यह हो जाएगा चर गए।
  • मुझे यह सब पाने के लिए अनाम कार्यों का उपयोग करने के लिए जाना जाता है, लेकिन एक बेहतर तरीका हो सकता है,

3

चूंकि आपने इसे जावास्क्रिप्ट के साथ टैग किया था, इसलिए मैं टाइमर नियंत्रण के साथ जाऊंगा क्योंकि आपके फ़ंक्शन के नाम 3, 5 और 8 सेकंड हैं। तो अपना टाइमर शुरू करें, 3 सेकंड में कॉल करें, पहला कॉल 5 सेकंड, दूसरा कॉल 8 सेकंड में, फिर जब यह हो जाए, टाइमर बंद कर दें।

सामान्य रूप से जावास्क्रिप्ट में आपके पास जो फ़ंक्शन के लिए सही है वह एक के बाद एक चल रहा है, लेकिन चूंकि ऐसा लगता है कि आप समयबद्ध एनीमेशन करने की कोशिश कर रहे हैं, एक टाइमर आपका सबसे अच्छा दांव होगा।


2

//sample01
(function(_){_[0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this[1].bind(this))},
	function(){$('#art2').animate({'width':'10px'},100,this[2].bind(this))},
	function(){$('#art3').animate({'width':'10px'},100)},
])

//sample02
(function(_){_.next=function(){_[++_.i].apply(_,arguments)},_[_.i=0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this.next)},
	function(){$('#art2').animate({'width':'10px'},100,this.next)},
	function(){$('#art3').animate({'width':'10px'},100)},
]);

//sample03
(function(_){_.next=function(){return _[++_.i].bind(_)},_[_.i=0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this.next())},
	function(){$('#art2').animate({'width':'10px'},100,this.next())},
	function(){$('#art3').animate({'width':'10px'},100)},
]);


क्या आप कृपया बता सकते हैं कि यह क्या है? अंडरस्कोर के लिए क्या बाध्य है? फ़ंक्शन को क्या सौंपा गया nextहै?
mtso

1
मैं jsfiddle का उपयोग करके नमूना 2 समझाता हूं। jsfiddle.net/mzsteyuy/3 यदि आप मुझे मोटे तौर पर समझाने की अनुमति देते हैं, तो नमूना 2 jsfiddle में कोड का एक छोटा तरीका है। अंडरस्कोर एरे है जो तत्व काउंटर वेलिबल (i) हैं और अगला और फंक्शन करते हैं [0] ~ [2]।
यौआ

1

आप इस तरह से वादों का भी उपयोग कर सकते हैं:

    some_3secs_function(this.some_value).then(function(){
       some_5secs_function(this.some_other_value).then(function(){
          some_8secs_function(this.some_other_other_value);
       });
    });

some_value.Then के अंदर से इसे एक्सेस करने के लिए आपको वैश्विक बनाना होगा

वैकल्पिक रूप से, बाहरी फ़ंक्शन से आप उस मान को वापस कर सकते हैं जिसका आंतरिक फ़ंक्शन उपयोग करेगा, जैसे:

    one(some_value).then(function(return_of_one){
       two(return_of_one).then(function(return_of_two){
          three(return_of_two);
       });
    });

0

मैं जावास्क्रिप्ट के सेटटाइमआउट के आधार पर एक 'WaitUntil' फ़ंक्शन का उपयोग करता हूं

/*
    funcCond : function to call to check whether a condition is true
    readyAction : function to call when the condition was true
    checkInterval : interval to poll <optional>
    timeout : timeout until the setTimeout should stop polling (not 100% accurate. It was accurate enough for my code, but if you need exact milliseconds, please refrain from using Date <optional>
    timeoutfunc : function to call on timeout <optional>
*/
function waitUntil(funcCond, readyAction, checkInterval, timeout, timeoutfunc) {
    if (checkInterval == null) {
        checkInterval = 100; // checkinterval of 100ms by default
    }
    var start = +new Date(); // use the + to convert it to a number immediatly
    if (timeout == null) {
        timeout = Number.POSITIVE_INFINITY; // no timeout by default
    }
    var checkFunc = function() {
        var end = +new Date(); // rough timeout estimations by default

        if (end-start > timeout) {
            if (timeoutfunc){ // if timeout function was defined
                timeoutfunc(); // call timeout function
            }
        } else {
            if(funcCond()) { // if condition was met
                readyAction(); // perform ready action function
            } else {
                setTimeout(checkFunc, checkInterval); // else re-iterate
            }
        }
    };
    checkFunc(); // start check function initially
};

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

जैसे

doSomething();
waitUntil(function() { return doSomething_value===1;}, doSomethingElse);
waitUntil(function() { return doSomethingElse_value===1;}, doSomethingUseful);

टिप्पणियाँ

दिनांक मोटे समय के अनुमान का कारण बनता है। अधिक सटीकता के लिए, कंसोल जैसे कार्यों पर स्विच करें। समय ()। ध्यान दें कि दिनांक अधिक क्रॉस-ब्राउज़र और विरासत समर्थन प्रदान करती है। यदि आपको सटीक मिलीसेकंड माप की आवश्यकता नहीं है; जब ब्राउज़र इसका समर्थन करता है, तो उसे वैकल्पिक रूप से परेशान न करें, न ही उसे लपेटें, और कंसोल.टाइम () प्रदान करें


0

यदि विधि 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>

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