javascript - मैं setTimeout() कॉलबैक में पैरामीटर कैसे पास कर सकता हूं?




parameters callback (13)

मेरे पास कुछ जावास्क्रिप्ट कोड है जो इस तरह दिखता है:

function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    var topicId = xmlhttp.responseText;
    setTimeout("postinsql(topicId)",4000);
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}

मुझे एक त्रुटि topicId है कि विषय topicId परिभाषित नहीं है मैं topicId setTimeout() फ़ंक्शन का उपयोग करने से पहले सबकुछ काम कर रहा था।

मैं चाहता हूं कि मेरे postinsql(topicId) फ़ंक्शन को कुछ समय बाद बुलाया जाए। मुझे क्या करना चाहिए?


@ जिरी वीटिस्का इस पोस्ट के लिए धन्यवाद, लेकिन आपके उदाहरण में कुछ गड़बड़ है। मुझे उस लक्ष्य को पारित करने की आवश्यकता है जो (यह) एक समयबद्ध कार्य में है और मैंने आपके दृष्टिकोण की कोशिश की। आईई 9 में परीक्षण - काम नहीं करता है। मैंने कुछ शोध भी किया और ऐसा प्रतीत होता है कि w3schools.com/jsref/met_win_settimeout.asp बताया गया w3schools.com/jsref/met_win_settimeout.asp कि तीसरा पैरामीटर स्क्रिप्ट भाषा का उपयोग किया जा रहा है। अतिरिक्त पैरामीटर के बारे में कोई जिक्र नहीं है।

इसलिए, मैंने @ meder के उत्तर का पालन किया और इस समस्या के साथ मेरी समस्या हल की:

$('.targetItemClass').hover(ItemHoverIn, ItemHoverOut);

function ItemHoverIn() {
 //some code here
}

function ItemHoverOut() {
    var THIS = this;
    setTimeout(
        function () { ItemHoverOut_timeout(THIS); },
        100
    );
}
function ItemHoverOut_timeout(target) {
    //do something with target which is hovered out
}

उम्मीद है, यह किसी और के लिए उपयोगी है।


SetTimeout में पैरामीटर का समर्थन करने के लिए सबसे आसान क्रॉस ब्राउज़र समाधान:

setTimeout(function() {
    postinsql(topicId);
}, 4000)

यदि आपको आईई 9 और निम्न का समर्थन नहीं करने पर कोई फर्क नहीं पड़ता है:

setTimeout(postinsql, 4000, topicId);

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout


कुछ जवाब सही हैं लेकिन शांत हैं।

मैं 4 साल बाद फिर से इसका जवाब दे रहा हूं, क्योंकि मैं अभी भी इस सवाल को हल करने के लिए अत्यधिक जटिल कोड में भाग लेता हूं। एक सुरुचिपूर्ण समाधान है।

सबसे पहले, सेटटाइमआउट को कॉल करते समय पहले पैरामीटर के रूप में स्ट्रिंग में पास न करें क्योंकि यह प्रभावी रूप से धीमी "eval" फ़ंक्शन पर कॉल को आमंत्रित करता है।

तो हम एक टाइमआउट फ़ंक्शन में पैरामीटर में कैसे पास करते हैं? बंद करने का उपयोग करके:

settopic=function(topicid){
  setTimeout(function(){
    //thanks to closure, topicid is visible here
    postinsql(topicid);
  },4000);
}

...
if (xhr.readyState==4){
  settopic(xhr.responseText);
}

कुछ ने टाइमआउट फ़ंक्शन को कॉल करते समय अनाम फ़ंक्शन का उपयोग करने का सुझाव दिया है:

if (xhr.readyState==4){
  setTimeout(function(){
    settopic(xhr.responseText);
  },4000);
}

वाक्यविन्यास काम करता है। लेकिन जब सेटटॉपिक कहा जाता है, यानी 4 सेकंड बाद, एक्सएचआर ऑब्जेक्ट एक जैसा नहीं हो सकता है। इसलिए चर को पूर्व-बाध्य करना महत्वपूर्ण है।


कुछ शोध और परीक्षण करने के बाद, केवल सही कार्यान्वयन है:

setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

setTimeout आपके फ़ंक्शन में सभी अतिरिक्त पैरामीटर पास करेगा ताकि उन्हें वहां संसाधित किया जा सके।

अज्ञात फ़ंक्शन बहुत ही बुनियादी सामग्री के लिए काम कर सकता है, लेकिन उस ऑब्जेक्ट के उदाहरण के दौरान जहां आपको "यह" उपयोग करना है, इसे काम करने का कोई तरीका नहीं है। कोई भी अनाम फ़ंक्शन विंडो पर इंगित करने के लिए "यह" बदल देगा, इसलिए आप अपना ऑब्जेक्ट संदर्भ खो देंगे।


डेविड मेस्टर का जवाब पैरामीटर का ख्याल रखना प्रतीत होता है जो सेटटाइम () पर कॉल के तुरंत बाद बदल सकता है लेकिन अनाम कार्य कहने से पहले। लेकिन यह बहुत बोझिल और बहुत स्पष्ट नहीं है। मैंने आईआईएफई (तुरंत कार्यवाही अभिव्यक्ति अभिव्यक्ति) का उपयोग करके एक ही चीज़ को करने का एक शानदार तरीका खोजा।

नीचे दिए गए उदाहरण में, मौजूदा लिस्ट वैरिएबल आईआईएफई को पास कर दिया गया है, जो इसे बंद होने तक बचाता है, जब तक कि देरी से कार्य नहीं किया जाता है। यहां तक ​​कि यदि परिवर्तनीय वर्तमान सूची कोड के तुरंत बाद बदल जाती है, तो setInterval() सही काम करेगा।

इस आईआईएफई तकनीक के बिना, सेटटाइम setTimeout() फ़ंक्शन निश्चित रूप से डीओएम में प्रत्येक h2 तत्व के लिए बुलाया जाएगा, लेकिन उन सभी कॉलों को केवल अंतिम h2 तत्व का टेक्स्ट मान दिखाई देगा।

<script>
  // Wait for the document to load.
  $(document).ready(function() {
  $("h2").each(function (index) {

    currentList = $(this).text();

    (function (param1, param2) {
        setTimeout(function() {
            $("span").text(param1 + ' : ' + param2 );
        }, param1 * 1000);

    })(index, currentList);
  });
</script>

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

मैंने सुना है कि आप setTimeout फ़ंक्शन पर तीसरे पैरामीटर के रूप में विषय को पार कर सकते हैं। ज्यादा जानकारी नहीं दी गई है लेकिन मुझे इसे काम करने के लिए पर्याप्त जानकारी मिली है, और यह सफारी में सफल है। मुझे नहीं पता कि "मिलीसेकंड त्रुटि" के बारे में उनका क्या मतलब है। यहां इसकी जांच कीजिए:

http://www.howtocreate.co.uk/tutorials/javascript/timers


मुझे पता है कि यह पुराना है लेकिन मैं इसके लिए अपना पसंदीदा (पसंदीदा) स्वाद जोड़ना चाहता था।

मुझे लगता है कि इसे प्राप्त करने के लिए एक बहुत ही पठनीय तरीका topicId को एक समारोह में पास करना है, जो बदले में विषय आईडी को आंतरिक रूप से संदर्भित करने के लिए तर्क का उपयोग करता है। यह मान तब भी नहीं बदलेगा जब topicId में बाहर के बाद जल्द ही बदला जाएगा।

var topicId = xmlhttp.responseText;
var fDelayed = function(tid) {
  return function() {
    postinsql(tid);
  };
}
setTimeout(fDelayed(topicId),4000);

या छोटा:

var topicId = xmlhttp.responseText;
setTimeout(function(tid) {
  return function() { postinsql(tid); };
}(topicId), 4000);

मुझे लगता है कि आप चाहते हैं:

setTimeout("postinsql(" + topicId + ")", 4000);

मैं हाल ही में एक लूप में एक setTimeout का उपयोग करने की आवश्यकता की अनूठी स्थिति में आया था। इसे समझने से आप समझने में मदद कर सकते हैं कि setTimeout पैरामीटर कैसे पास करें।

विधि 1

forEach के suggestion अनुसार, forEach और Object.keys उपयोग करें:

var testObject = {
    prop1: 'test1',
    prop2: 'test2',
    prop3: 'test3'
};

Object.keys(testObject).forEach(function(propertyName, i) {
    setTimeout(function() {
        console.log(testObject[propertyName]);
    }, i * 1000);
});

मैं इस विधि की सिफारिश करता हूं।

विधि 2

bind प्रयोग करें:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }.bind(this, propertyName), i++ * 1000);
}

JSFiddle: http://jsfiddle.net/MsBkW/

विधि 3

या यदि आप forEach या bind उपयोग नहीं कर सकते bind , तो IIFE उपयोग करें:

var i = 0;
for (var propertyName in testObject) {
    setTimeout((function(propertyName) {
        return function() {
            console.log(testObject[propertyName]);
        };
    })(propertyName), i++ * 1000);
}

विधि 4

लेकिन अगर आपको आईई <10 की परवाह नहीं है, तो आप फैबियो के suggestion का उपयोग कर सकते हैं:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }, i++ * 1000, propertyName);
}

विधि 5 (ईएस 6)

एक ब्लॉक स्कोप्ड चर का प्रयोग करें:

let i = 0;
for (let propertyName in testObject) {
    setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);
}

हालांकि मैं अभी भी ES6 में Object.keys के लिए forEach का उपयोग करने की Object.keys करता forEach


मैंने इस चरण को कैसे हल किया?

ऐसे ही :

setTimeout((function(_deepFunction ,_deepData){
    var _deepResultFunction = function _deepResultFunction(){
          _deepFunction(_deepData);
    };
    return _deepResultFunction;
})(fromOuterFunction, fromOuterData ) , 1000  );

setTimeout किसी फ़ंक्शन के संदर्भ का इंतजार करता है, इसलिए मैंने इसे बंद करने में बनाया है, जो मेरे डेटा को समझता है और मेरे डेटा के एक अच्छे उदाहरण के साथ एक फ़ंक्शन लौटाता है!

शायद आप इस हिस्से को बेहतर बना सकते हैं:

_deepFunction(_deepData);

// change to something like :
_deepFunction.apply(contextFromParams , args); 

मैंने क्रोम, फ़ायरफ़ॉक्स और आईई पर इसका परीक्षण किया और यह अच्छी तरह से निष्पादित है, मुझे प्रदर्शन के बारे में पता नहीं है लेकिन मुझे काम करने की आवश्यकता है।

एक नमूना परीक्षण:

myDelay_function = function(fn , params , ctxt , _time){
setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.call(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// the function to be used :
myFunc = function(param){ console.log(param + this.name) }
// note that we call this.name

// a context object :
myObjet = {
    id : "myId" , 
    name : "myName"
}

// setting a parmeter
myParamter = "I am the outer parameter : ";

//and now let's make the call :
myDelay_function(myFunc , myParamter  , myObjet , 1000)

// this will produce this result on the console line :
// I am the outer parameter : myName

शायद आप इसे अधिक महत्व देने के लिए हस्ताक्षर बदल सकते हैं:

myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.apply(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// and try again :
for(var i=0; i<10; i++){
   myNass_setTimeOut(console.log ,1000 , [i] , console)
}

और मूल प्रश्न का उत्तर देने के लिए finaly:

 myNass_setTimeOut( postinsql, 4000, topicId );

उम्मीद है कि यह मदद कर सकता है!

ps: क्षमा करें लेकिन अंग्रेजी यह मेरी मातृभाषा नहीं है!


यह सभी ब्राउज़रों में काम करता है (आईई एक विषम गेंद है)

setTimeout( (function(x) {
return function() {
        postinsql(x);
    };
})(topicId) , 4000);

सामान्य रूप से, यदि आपको विशिष्ट पैरामीटर के साथ कॉलबैक के रूप में फ़ंक्शन को पास करने की आवश्यकता है, तो आप उच्च ऑर्डर फ़ंक्शंस का उपयोग कर सकते हैं। यह ES6 के साथ सुंदर सुरुचिपूर्ण है:

const someFunction = (params) => () => {
  //do whatever
};

setTimeout(someFunction(params), 1000);

या अगर कुछ someFunction पहला आदेश है:

setTimeout(() => someFunction(params), 1000); 

setTimeout(function() {
    postinsql(topicId);
}, 4000)

आपको किसी स्ट्रिंग के बजाय पैरामीटर के रूप में अज्ञात फ़ंक्शन को फ़ीड करने की आवश्यकता होती है, बाद की विधि को ECMAScript विनिर्देश के अनुसार भी काम नहीं करना चाहिए, लेकिन ब्राउज़र केवल उन्मुख हैं। यह उचित समाधान है, setTimeout() या setInterval() का उपयोग करते समय स्ट्रिंग को 'फ़ंक्शन' के रूप में पारित करने पर भरोसा न करें, यह धीमा है क्योंकि इसका मूल्यांकन किया जाना चाहिए और यह सही नहीं है।

अद्यतन करें:

जैसा कि हॉबलिन ने सवाल पर अपनी टिप्पणियों में कहा था, अब आप Function.prototype.bind() का उपयोग कर सेटटाइमआउट के अंदर फ़ंक्शन में तर्क पारित कर सकते हैं।

उदाहरण:

setTimeout(postinsql.bind(null, topicId), 4000);




settimeout