javascript - 예제 - 자바스크립트 비동기 프로그래밍




setTimeout() 콜백에 매개 변수를 전달하려면 어떻게해야합니까? (14)

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

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

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

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

postinsql(topicId) 함수가 얼마 후에 호출 postinsql(topicId) 바랍니다. 어떻게해야합니까?


@ 지리 베티스카 (Jiri Vetyska)는 게시물에 감사하지만 귀하의 예에서 잘못된 점이 있습니다. 나는 시간 초과 된 기능에 끈적 거리는 표적 (이)을 통과해야했고 나는 당신의 접근 방식을 시도했다. IE9에서 테스트되었습니다 - 작동하지 않습니다. 나는 또한 약간의 연구를했고 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
}

희망, 이것은 다른 누군가에게 유용합니다.


David Meister의 대답은 setTimeout ()을 호출 한 직후에 변경 될 수 있지만 익명의 함수가 호출되기 전에 변경 될 수있는 매개 변수를 처리하는 것으로 보입니다. 하지만 너무 복잡하고 그리 명확하지 않습니다. IIFE (즉시 inviked 함수 표현식)를 사용하여 거의 동일한 일을하는 우아한 방법을 발견했습니다.

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

이 IIFE 기법을 사용하지 않으면 setTimeout() 함수가 DOM의 각 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>

IE에서 세 번째 optonal 매개 변수에 문제가 있고 closure를 사용하면 변수를 변경하는 것을 방지하고 (예를 들어 루프에서) 원하는 결과를 얻는 것이므로 다음 해결책을 제안합니다.

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

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

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



나는 그것이 오래되었음을 알고 있지만 이것에 나의 (선호하는) 풍미를 더하고 싶었다.

이를 달성하기위한 아주 읽기 쉬운 방법은 topicId 를 함수에 전달하는 topicId .이 함수는 인수를 사용하여 내부적으로 항목 ID를 참조합니다. 곧바로 외부의 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);

당신은 'apply ()'와 같은 것을 기본 함수로 사용할 수 있습니다. 배열에서 더 많은 수의 인수를 요구 사항으로 전달할 수 있습니다.

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

몇 가지 연구와 테스트를 수행 한 후에 올바른 구현은 다음과 같습니다.

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

setTimeout은 모든 추가 매개 변수를 함수에 전달하여 거기에서 처리 할 수있게합니다.

익명의 함수는 매우 기본적인 것들을 처리 할 수 ​​있지만, "this"를 사용해야하는 객체의 인스턴스 내에서는 익명의 함수를 작동시킬 수있는 방법이 없습니다. 어떤 익명의 함수는 윈도우를 가리 키도록 "this"를 바꿀 것이므로 객체 참조를 잃을 것입니다.


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

그 것처럼 :

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

희망이 도움이 될 수 있습니다!

추신 : 미안하지만 영어 그것은 내 모국어가 아니야!


이것은 모든 브라우저에서 작동합니다 (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); 

일부 답변은 정확하지만 복잡한 내용입니다.

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

우선, 느린 "eval"함수에 대한 호출을 효과적으로 호출하기 때문에 setTimeout을 호출 할 때 첫 번째 매개 변수로 문자열을 전달하지 마십시오.

그렇다면 타임 아웃 함수에 매개 변수를 전달하는 방법은 무엇입니까? 클로저 사용 :

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

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

어떤 사람들은 timeout 함수를 호출 할 때 익명의 함수를 사용하도록 제안했다.

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

문법이 작동합니다. 그러나 settopic이 호출 될 때까지, 즉 4 초 후에 XHR 객체가 같지 않을 수 있습니다. 따라서 변수미리 바인딩하는 것이 중요 합니다 .



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

문자열이 아닌 매개 변수로 익명 함수를 제공해야하는데, 후자의 메서드는 ECMAScript 사양에 따라 작동하지 않아야하지만 브라우저는 그냥 관대합니다. 이것은 적절한 해결책입니다. setTimeout() 또는 setInterval() 사용할 때 문자열을 '함수'로 전달하지 말고 평가해야하기 때문에 속도가 느려지고 옳지 않습니다.

최신 정보:

Hobblin이 질문에 대한 그의 의견에서, 이제 Function.prototype.bind() 사용하여 setTimeout 내부에서 함수에 인수를 전달할 수 있습니다.

예:

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






settimeout