program story

매개 변수를 setTimeout () 콜백에 어떻게 전달할 수 있습니까?

inputbox 2020. 9. 29. 07:43
반응형

매개 변수를 setTimeout () 콜백에 어떻게 전달할 수 있습니까?


다음과 같은 JavaScript 코드가 있습니다.

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

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

topicId정의되지 않은 오류가 발생했습니다 setTimeout(). 함수를 사용하기 전에 모든 것이 작동했습니다 .

postinsql(topicId)얼마 후 함수를 호출 하고 싶습니다 . 어떻게해야합니까?


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

익명 함수를 문자열 대신 매개 변수로 제공해야합니다. 후자의 방법은 ECMAScript 사양에 따라 작동하지 않아야하지만 브라우저는 관대합니다. 이것은 적절한 해결책입니다. setTimeout()or를 사용할 때 문자열을 '함수'로 전달하는 것에 의존하지 마십시오 setInterval(). 평가해야하고 옳지 않기 때문에 속도가 느립니다.

최신 정보:

Hobblin이 질문에 대한 의견에서 말했듯이 이제 setTimeout 내부의 함수에 인수를 전달할 수 있습니다. Function.prototype.bind()

예:

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

최신 브라우저에서 "setTimeout"은 타이머가 끝날 때 내부 함수에 매개 변수로 전송되는 세 번째 매개 변수를 수신합니다.

예:

var hello = "Hello World";
setTimeout(alert, 1000, hello);

자세한 내용은:


조사 및 테스트를 수행 한 후 올바른 구현은 다음과 같습니다.

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

setTimeout은 모든 추가 매개 변수를 함수에 전달하므로 거기서 처리 할 수 ​​있습니다.

익명 함수는 매우 기본적인 작업에 대해 작동 할 수 있지만 "this"를 사용해야하는 객체의 인스턴스 내에서는 작동하도록 만들 방법이 없습니다. 익명 함수는 "this"가 창을 가리 키도록 변경하므로 개체 참조를 잃게됩니다.


이것은 이미 "정확한"답변이있는 매우 오래된 질문이지만 여기에 아무도 언급하지 않은 또 다른 접근 방식을 언급 할 것이라고 생각했습니다. 이것은 우수한 밑줄 라이브러리 에서 복사하여 붙여 넣습니다 .

_.delay = function(func, wait) {
  var args = slice.call(arguments, 2);
  return setTimeout(function(){ return func.apply(null, args); }, wait);
};

당신의 setTimeout 호출 함수에 원하는만큼 당신은 많은 인수로 전달할 수 있습니다 추가 보너스 (물론, 일반적으로 보너스) 당신의 setTimeout를 호출 할 때 함수에 전달되는 인수의 값이 냉동만큼 그들이 값을 변경 그렇다면, setTimeout ()이 호출 될 때와 시간이 초과 될 때 사이의 어느 시점에서, 음 ... 더 이상 끔찍하게 실망하지 않습니다. :)

내가 의미하는 바를 볼 수 있는 바이올린 이 있습니다.


최근 setTimeout루프 에서 를 사용해야하는 독특한 상황을 발견했습니다 . 이를 이해하면에 매개 변수를 전달하는 방법을 이해하는 데 도움이됩니다 setTimeout.

방법 1

사용 forEachObject.keys, Sukima의 제안에 따라 :

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

당신이 사용할 수없는 경우 또는 forEachbind, 사용 인생을 :

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

방법 4

그러나 IE <10에 대해 신경 쓰지 않는다면 Fabio의 제안을 사용할 수 있습니다 .

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

방법 5 (ES6)

블록 범위 변수를 사용하십시오.

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

여전히 ES6에서 Object.keyswith forEach사용 하는 것이 좋습니다 .


Hobblin은 이미 질문에 대해 이것을 언급했지만 실제로 답이되어야합니다!

사용 Function.prototype.bind()은이를 수행하는 가장 깨끗하고 유연한 방법입니다 ( this컨텍스트 를 설정할 수 있다는 추가 보너스 포함 ).

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

자세한 내용은 다음 MDN 링크를 참조하십시오.
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function / bind # With_setTimeout


일부 답변은 정확하지만 복잡합니다.

나는이 질문을 정확히 해결하기 위해 여전히 지나치게 복잡한 코드를 실행하고 있기 때문에 4 년 후 다시 대답하고 있습니다. 우아한 해결책이 있습니다.

먼저 setTimeout을 호출 할 때 첫 번째 매개 변수로 문자열을 전달하지 마십시오. 이는 느린 "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);
}

구문이 작동합니다. 그러나 settopic이 호출되는 시간 (예 : 4 초 후)에는 XHR 객체가 동일하지 않을 수 있습니다. 따라서 변수미리 바인딩하는 것이 중요 합니다 .


내 대답 :

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

설명:

생성 된 익명 함수는 다른 익명 함수를 반환합니다. 이 함수는 원래 전달 된에 액세스 할 수 topicId있으므로 오류가 발생하지 않습니다. 첫 번째 익명 함수가 즉시 호출되어를 전달 topicId하므로 지연이있는 등록 된 함수 topicId는 호출시 클로저를 통해 액세스 할 수 있습니다.

또는

이것은 기본적으로 다음으로 변환됩니다.

setTimeout(function() {
  postinsql(topicId); // topicId inside higher scope (passed to returning function)
}, 4000);

편집 : 나는 같은 대답을 보았으므로 그의 것을보십시오. 그러나 나는 그의 대답을 훔치지 않았다! 나는 단지 보는 것을 잊었다. 설명을 읽고 코드를 이해하는 데 도움이되는지 확인하십시오.


바꾸다

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

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

또는 더 나은 방법은 문자열 표현식을 익명 함수로 바꾸는 것입니다.

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

편집하다:

Brownstone의 설명이 잘못되었습니다. Firebug 콘솔에서 실행하여 설명 된대로 의도 한대로 작동합니다.

(function() {
  function postinsql(id) {
    console.log(id);
  }
  var topicId = 3
  window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds
})();

문자열을 setTimeout호출 eval()하고 대신 함수 를 전달하므로 문자열 전달을 피해야한다는 다른 사람들과 동의 합니다.


setTimeout에서 매개 변수를 지원하는 가장 쉬운 크로스 브라우저 솔루션 :

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

IE 9 이하를 지원하지 않아도 괜찮다면 :

setTimeout(postinsql, 4000, topicId);

setTimeout 데스크톱 브라우저 호환성

setTimeout 모바일 브라우저 호환성

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


나는 그것이 오래되었다는 것을 알고 있지만 이것에 나의 (선호하는) 맛을 더하고 싶었습니다.

이 작업을 수행하는 꽤 읽기 쉬운 방법은을 topicId함수 에 전달 하는 것입니다. 그러면 내부적으로 주제 ID를 참조하는 인수를 사용합니다. 이 값은 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);

David Meister의 대답은 setTimeout () 호출 직후 익명 함수가 호출되기 전에 변경 될 수있는 매개 변수를 처리하는 것 같습니다. 하지만 너무 번거롭고 명확하지 않습니다. IIFE (즉각적인 함수 표현)를 사용하여 거의 동일한 작업을 수행하는 우아한 방법을 발견했습니다.

아래 예제에서 currentList변수는 IIFE에 전달되어 지연된 함수가 호출 될 때까지 폐쇄에 저장됩니다. currentList표시된 코드 직후에 변수가 변경 되더라도은 setInterval()올바른 작업을 수행합니다.

이 IIFE 기술이 없으면 setTimeout()함수는 확실히 h2DOM의 요소에 대해 호출되지만 모든 호출은 마지막 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>

이것은 모든 브라우저에서 작동합니다 (IE는 이상한 것입니다)

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

일반적으로 특정 매개 변수가있는 콜백으로 함수를 전달해야하는 경우 고차 함수를 사용할 수 있습니다. 이것은 ES6에서 매우 우아합니다.

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

setTimeout(someFunction(params), 1000);

또는 someFunction첫 주문 인 경우 :

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

오류 메시지에 따라 topicId가 "정의되지 않음"인 이유는 setTimeout이 실행될 때 로컬 변수로 존재했지만 postinsql에 대한 지연된 호출이 발생했을 때가 아니기 때문입니다. 가변 수명은 특히 "this"를 객체 참조로 전달하는 것과 같은 작업을 시도 할 때주의해야 할 중요한 사항입니다.

setTimeout 함수에 세 번째 매개 변수로 topicId를 전달할 수 있다고 들었습니다. 세부 사항은 많지 않지만 작동하도록 충분한 정보를 얻었으며 Safari에서 성공했습니다. 하지만 "밀리 초 오류"에 대해 무슨 의미인지 모르겠습니다. 여기에서 확인하세요 :

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


이 단계를 어떻게 해결 했습니까?

그냥 그렇게 :

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); 

나는 크롬, 파이어 폭스 및 IE에서 테스트했으며 잘 실행되지만 성능에 대해서는 모르지만 작동해야했습니다.

샘플 테스트 :

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)
}

그리고 마지막으로 원래 질문에 답하십시오.

 myNass_setTimeOut( postinsql, 4000, topicId );

그것이 도움이 될 수 있기를 바랍니다!

추신 : 미안하지만 영어 내 모국어가 아닙니다!


변수를 매개 변수로 전달하려면 이것을 시도하십시오.

요구 사항이 function이고 var as parmas이면 이것을 시도하십시오.

setTimeout((param1,param2) => { 
     alert(param1 + param2);
     postinsql(topicId);
},2000,'msg1', 'msg2')

요구 사항이 매개 변수로만 변수이면 다음을 시도하십시오.

setTimeout((param1,param2) => { alert(param1 + param2) },2000,'msg1', 'msg2')

ES5 및 ES6에서 이것을 시도 할 수 있습니다.


다음과 같은 'apply ()'의 기본 기능을 시도해 볼 수 있으며 배열의 요구 사항으로 더 많은 인수를 전달할 수 있습니다.

function postinsql(topicId)
{
  //alert(topicId);
}
setTimeout(
       postinsql.apply(window,["mytopic"])
,500);

매개 변수를 setTimeout 콜백 함수에 다음과 같이 전달할 수 있습니다.

setTimeout (함수, 밀리 초, param1, param2, ...)

예.

function myFunction() {
  setTimeout(alertMsg, 3000, "Hello");
}

function alertMsg(message) {
    alert(message)
}

@Jiri Vetyska는 게시물을 주셔서 감사하지만 귀하의 예에는 잘못된 것이 있습니다. 나는 시간 초과 기능에 (이) 호버링 된 대상을 전달해야했으며 귀하의 접근 방식을 시도했습니다. IE9에서 테스트-작동하지 않습니다. 나는 또한 약간의 조사를했고 여기 에서 지적한 바와 같이 세 번째 매개 변수는 사용되는 스크립트 언어 인 것으로 보입니다 . 추가 매개 변수에 대한 언급이 없습니다.

그래서 @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
}

희망, 이것은 다른 사람에게 유용합니다.


IE의 세 번째 optonal 매개 변수에 문제가 있고 클로저를 사용하면 변수 (예 : 루프)를 변경하고 원하는 결과를 얻을 수 없으므로 다음 솔루션을 제안합니다.

다음과 같이 재귀를 사용해 볼 수 있습니다.

var i = 0;
var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"];

if(hellos.length > 0) timeout();

function timeout() {                
    document.write('<p>' + hellos[i] + '<p>');
    i++;
    if (i < hellos.length)
        setTimeout(timeout, 500);
}

이 변수를 변경하지 않고 무한 재귀를 피하기 위해 적절한 재귀 조건을 작성해야합니다.


// 다음은 세 가지 매우 간단하고 간결한 답변입니다.

function fun() {
    console.log(this.prop1, this.prop2, this.prop3);
}

let obj = { prop1: 'one', prop2: 'two', prop3: 'three' };

let bound = fun.bind(obj);

setTimeout(bound, 3000);

 // or

function funOut(par1, par2, par3) {

  return function() { 

    console.log(par1, par2, par3);

  }
};

setTimeout(funOut('one', 'two', 'three'), 5000);

 // or

let funny = function(a, b, c) { console.log(a, b, c); };

setTimeout(funny, 2000, 'hello', 'worldly', 'people');

나는 당신이 원한다고 생각합니다 :

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

// 다음은 세 가지 매우 간단하고 간결한 답변입니다.

function fun() {
    console.log(this.prop1, this.prop2, this.prop3);
}

let obj = { prop1: 'one', prop2: 'two', prop3: 'three' };

let bound = fun.bind(obj);

setTimeout(bound, 3000);

 // or

function funOut(par1, par2, par3) {

  return function() { 

    console.log(par1, par2, par3);

  }
};

setTimeout(funOut('one', 'two', 'three'), 5000);

 // or

let funny = function(a, b, c) { console.log(a, b, c); };

setTimeout(funny, 2000, 'hello', 'worldly', 'people');

참고 URL : https://stackoverflow.com/questions/1190642/how-can-i-pass-a-parameter-to-a-settimeout-callback

반응형