Jak mogę przekazać parametr do wywołania zwrotnego setTimeout ()?


825

Mam trochę kodu JavaScript, który wygląda następująco:

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

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

Pojawia się błąd, który topicIdnie został zdefiniowany. Wszystko działało przed użyciem tej setTimeout()funkcji.

Chcę, aby moja postinsql(topicId)funkcja została wywołana po pewnym czasie. Co powinienem zrobić?


75
trochę boli komentowanie tak starego tematu, ale muszę tylko zaoferować trzecią wersję (która moim zdaniem jest znacznie czystsza): setTimeout (postinsql.bind (null, topicId), 4000)
Hobblin

14
@Hobblin: dlaczego miałoby boleć ustawianie rekordu prosto? Czy nie zaszkodziłoby to innym, gdyby wylądowali na tym popularnym pytaniu i zobaczyli stary, wypaczony styl rozmowy?
Dan Dascalescu


@dbliss Moja sugestia została już wspomniana w kilku odpowiedziach i dodana jako odpowiedź tutaj: stackoverflow.com/a/15620038/287130 Ale cieszę się, że moja sugestia została doceniona;)
Hobblin

@Hobblin ah, wielkie dzięki za zwrócenie na to uwagi. przewijałem się, szukając odpowiedzi wysłanej przez ciebie i tęskniłem.
dbliss

Odpowiedzi:


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

Musisz podać anonimową funkcję jako parametr zamiast ciągu, ta druga metoda nie powinna nawet działać zgodnie ze specyfikacją ECMAScript, ale przeglądarki są po prostu pobłażliwe. Jest to właściwe rozwiązanie, nigdy nie polegaj na przekazywaniu łańcucha jako „funkcji” podczas używania setTimeout()lub setInterval(), jest on wolniejszy, ponieważ należy go ocenić i po prostu nie jest odpowiedni.

AKTUALIZACJA:

Jak powiedział Hobblin w swoich komentarzach do pytania, teraz możesz przekazywać argumenty do funkcji wewnątrz setTimeout za pomocą Function.prototype.bind().

Przykład:

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

30
window.setTimeoutjest metodą DOM i jako taka nie jest zdefiniowana w specyfikacji ECMAScript. Przekazywanie ciągu zawsze działało w przeglądarkach i jest de facto standardem - w rzeczywistości możliwość przekazywania obiektu funkcji została dodana później, w JavaScript 1.2 - jest to wyraźnie część specyfikacji roboczej HTML5 ( whatwg.org/specs/web -apps / current-work / multipage /… ). Jednak użycie ciągu zamiast obiektu funkcji jest ogólnie uważane za kiepski styl, ponieważ jest to zasadniczo forma opóźniona eval().
Miles,

2
var temp = setTimeout (function () {postinsql (topicId);}, 4000); clearTimeout (temp); ??
Josh Mc

12
Co by się stało, gdyby topicId został zmieniony po ustawieniu limitu czasu, ale przed wywołaniem funkcji?
pilau

22
@pilau to właśnie mój problem: jeśli zmienne użyte w funkcji anonimowej zmienią się przed upływem limitu czasu (np. w pętli for), to również zmieni się wewnątrz funkcji. Tak więc w moim przykładzie ustawienie 5 różnych limitów czasu w pętli for zakończyło się na użyciu tych samych zmiennych. Zachowaj ostrożność podczas korzystania z tej odpowiedzi!
Cristian

10
@pilau przy użyciu innego zamknięcia pomoże topicId = 12; funkcja postinsql (topicId) {console.log (topicId); } funkcja setTimeOutWithClosure (topicId) {setTimeout (function () {postinsql (topicId);}, 1000)} setTimeOutFunction (topicId); topicId = 13;
Halis Yılboğa

727

W nowoczesnych przeglądarkach „setTimeout” otrzymuje trzeci parametr, który jest wysyłany jako parametr do funkcji wewnętrznej na końcu timera.

Przykład:

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

Więcej szczegółów:


56
Nie jestem pewien, dlaczego ta odpowiedź nie została wybrana jako najlepsza. Korzystanie z funkcji anonimowej działa, oczywiście, ale jeśli możesz po prostu przekazać trzeci parametr do pierwotnego wywołania funkcji setTimeout ... dlaczego nie?
Kris Schouw,

54
Ponieważ nie działa w wersjach IE, nadal bardzo dużo na wolności.
Aaron

4
Ta odpowiedź faktycznie umożliwiła mi przekazanie obiektu zdarzenia, inne metody tego nie zrobiły. Miałem już anonimową funkcję.
Glenn Plas,

27
Zdecydowanie lepsza odpowiedź. Jeśli masz kod, który modyfikuje parametr między wywołaniem „setTimeout” a faktycznym wykonaniem funkcji anonimowej - funkcja anonimowa otrzyma zmodyfikowaną wartość, a nie taką, jaka była w momencie wywołania setTimeout. np .: for (var i = 0; i <100; i ++) {setTimeout (function () {console.write (i);}, 0); } rejestruje to „100” 100 razy (testowane na FF). Obecna odpowiedź pomaga tego uniknąć.
korzeń

1
Zgodnie z developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout argumenty wywołania zwrotnego dla Internet Explorera są obsługiwane tylko w wersjach> = 10, bądź ostrożny, ponieważ w wielu witrynach ie8 i ie9 nadal ma odpowiedni udział.
le0diaz

154

Po przeprowadzeniu pewnych badań i testów jedyną poprawną implementacją jest:

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

setTimeout przekaże wszystkie dodatkowe parametry do twojej funkcji, aby mogły zostać tam przetworzone.

Funkcja anonimowa może działać w przypadku bardzo podstawowych rzeczy, ale w przypadku obiektu, w którym musisz użyć „tego”, nie ma sposobu, aby to zadziałało. Każda anonimowa funkcja zmieni „to”, aby wskazywała okno, więc stracisz referencję do obiektu.


24
Ze smutkiem w sercu muszę poinformować: to nie działa w Internet Explorerze. : / Wszystkie dodatkowe parametry są zdefiniowane jako niezdefiniowane.
Amalgovinus

6
Po prostu używamvar that = this; setTimeout( function() { that.foo(); }, 1000);
Ed Williams

2
Jest to poprawne i jest określone w HTML5. whatwg.org/specs/web-apps/current-work/multipage/…
Garrett

4
To jest dokładnie taka sama odpowiedź jak u Fabio .
Dan Dascalescu

1
Zgodnie z developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout argumenty wywołania zwrotnego dla Internet Explorera są obsługiwane tylko w wersjach> = 10, bądź ostrożny, ponieważ w wielu witrynach ie8 i ie9 nadal ma odpowiedni udział.
le0diaz

45

To bardzo stare pytanie z już „poprawną” odpowiedzią, ale pomyślałem, że wspomnę o innym podejściu, o którym nikt tu nie wspomniał. Jest to kopiowane i wklejane z doskonałej biblioteki podkreślenia :

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

Możesz przekazać tyle argumentów, ile chcesz, do funkcji wywoływanej przez setTimeout, a jako dodatkowy bonus (cóż, zazwyczaj bonus) wartości argumentów przekazywanych do twojej funkcji są zamrożone po wywołaniu setTimeout, więc jeśli zmienią wartość w pewnym momencie pomiędzy wywołaniem setTimeout () a upływem czasu, cóż ... to już nie jest tak strasznie frustrujące :)

Oto skrzypce, w której możesz zobaczyć, co mam na myśli.


7
Ta odpowiedź faktycznie działa, ale wydaje się, że masz bibliotekę, której ja nie mam. Oto mała poprawka, aby zadziałało: zamiast slice.call użyj Array.prototype.slice.call (argumenty, 2)
Melanie

7
@Melanie „jakaś biblioteka”? W odpowiedzi powiedziałem, że jest to biblioteka podkreślająca - underscorejs.org . Ale tak, Array.prototype.slice jest aliasowany do wycinania w tej bibliotece, więc musisz to zrobić sam, jeśli go nie używasz, dobre miejsce :)
David Meister

38

Niedawno natknąłem się na wyjątkowej sytuacji konieczności użyć setTimeoutw pętli . Zrozumienie tego może pomóc ci zrozumieć, jak przekazać parametry setTimeout.

Metoda 1

Użyj forEachi Object.keys, zgodnie z sugestią Sukimy :

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

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

Polecam tę metodę.

Metoda 2

Użyj 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/

Metoda 3

Lub jeśli nie możesz użyć forEachlub bind, użyj IIFE :

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

Metoda 4

Ale jeśli nie zależy ci na IE <10, możesz skorzystać z sugestii Fabio :

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

Metoda 5 (ES6)

Użyj zmiennej o zasięgu blokowym:

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

Chociaż nadal polecam używanie Object.keysz forEachES6.


2
Uwaga: .bindnie będzie działać dla IE8 i niższych [ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ]. Skończyło się na rozwiązaniu
Schiena

1
Jeśli jesteś w środowisku, które używa, bindto także w środowisku, które oferuje Object.keysi forEach. Możesz stracić pętlę for i uzyskać w tym procesie zakres funkcji „darmowej” (jak u dwóch ptaków z jednym kamieniem nie zasobem).
Sukima

@ David Sherret na wypadek, gdybyś go wcześniej nie używał, zdecydowanie sprawdź asyncbibliotekę ( github.com/caolan/async ). Używamy go szeroko w Sails i osiągnęliśmy świetne wyniki przez ostatnie 2 lata. Zapewnia metody zarówno równolegle i szeregowo asynchronicznych forEach, map, reduce, itd.
mikermcneil

25

Hobblin już skomentował to pytanie, ale tak naprawdę powinna to być odpowiedź!

Korzystanie Function.prototype.bind()jest najczystszym i najbardziej elastycznym sposobem na zrobienie tego (z dodatkową korzyścią z możliwości ustawienia thiskontekstu):

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

Aby uzyskać więcej informacji, zobacz te łącza 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


ten kontekst można przekazać pierwszym argumentem bindsetTimeout(postinsql.bind(this, topicId), 4000);
Giuseppe Galano,

@GiuseppeGalano całkowicie, wspomniałem o tym w mojej odpowiedzi, ale nie jest to potrzebne w tym przykładzie :)
dain

Fascynujące, ile połysku w porównaniu z częściowymi aplikacjami bind. To naprawdę tworzy czytelny kod.
Sukima

bind () jest obsługiwany tylko z IE9 +, więc to podejście nie będzie działać dla <IE9
Sanjeev

@Sanjeev Użyj podkładki ES5, aby działała w starszych IE: github.com/es-shims/es5-shim
gregers

17

Niektóre odpowiedzi są poprawne, ale zawiłe.

Odpowiadam na to ponownie, 4 lata później, ponieważ wciąż napotykam na zbyt skomplikowany kod, aby rozwiązać dokładnie to pytanie. Jest eleganckie rozwiązanie.

Przede wszystkim nie należy podawać ciągu jako pierwszego parametru podczas wywoływania setTimeout, ponieważ skutecznie wywołuje wywołanie wolnej funkcji „eval”.

Jak więc przekazać parametr do funkcji limitu czasu? Korzystając z zamknięcia:

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

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

Niektórzy sugerują użycie funkcji anonimowej podczas wywoływania funkcji limitu czasu:

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

Składnia się sprawdza. Ale do czasu wywołania funkcji osadniczej, tj. 4 sekundy później, obiekt XHR może nie być taki sam. Dlatego ważne jest wstępne wiązanie zmiennych .


1
+1 za czytelne rozwiązanie, nieco inne niż moje. Podczas gdy masz funkcję setTimeout wewnątrz funkcji setopy, ja mam funkcję fDelayed (twoją osadę) wewnątrz funkcji setTimeout.
Dominic

11

Moja odpowiedź:

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

Wyjaśnienie:

Utworzona funkcja anonimowa zwraca inną funkcję anonimową. Ta funkcja ma dostęp do pierwotnie przekazanego topicId, więc nie spowoduje błędu. Pierwsza anonimowa funkcja jest natychmiast wywoływana, przekazując topicId, dzięki czemu zarejestrowana funkcja z opóźnieniem ma dostęp topicIdw momencie wywołania przez zamknięcia.

LUB

Zasadniczo konwertuje się na:

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

EDYCJA: Widziałem tę samą odpowiedź, więc spójrz na jego. Ale nie ukradłem jego odpowiedzi! Po prostu zapomniałem spojrzeć. Przeczytaj wyjaśnienie i sprawdź, czy to pomaga zrozumieć kod.


To najlepsza odpowiedź. Wiele z tych rozwiązań nie uwzględni nawet limitu czasu. Dlaczego jednak zawijasz pierwszą anonimową funkcję w nawiasie? Nie sądzę, aby były one konieczne do osiągnięcia tego.
Robert Henderson

to najlepsza odpowiedź 👍, ale musiałem wykonać klon, ponieważ gdy wartości takie ulegną topicIdzmianie, zmienia się również wartość limitu czasu. Naprawił go klon
pariola

10

Zastąpić

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

z

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

lub jeszcze lepiej, zamień wyrażenie łańcuchowe na anonimową funkcję

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

EDYTOWAĆ:

Komentarz Brownstone'a jest niepoprawny, będzie działał zgodnie z przeznaczeniem, jak pokazano, uruchamiając to w konsoli Firebug

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

Zauważ, że zgadzam się z innymi, że powinieneś unikać przekazywania ciągu znaków, setTimeoutponieważ spowoduje to wywołanie eval()ciągu i przekazanie funkcji.


To nie zadziała, ponieważ wynik postinsql (topicId) zostanie wykonany przez setTimeout. Musisz zawinąć ją w funkcję jak przy pierwszej odpowiedzi lub użyć pomocnika, takiego jak .curry () - setTimeout (postinsql.curry (topidId), 4000);
shuckster

2
@brownstone: To nieprawda. Ciąg zostanie oceniony, gdy upłynie limit czasu.
Miles

9

Możesz przekazać parametr do funkcji zwrotnej setTimeout jako:

setTimeout (funkcja, milisekundy, param1, param2, ...)

na przykład.

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

function alertMsg(message) {
    alert(message)
}

1
Czy ktoś może mi powiedzieć, dlaczego ta odpowiedź nie jest preferowana? to moim zdaniem najprostszy sposób! Tak proste jaksetTimeout( (p) => { console.log(p); }, 1000, "hi" );
Mazhar Zandsalimi,

1
Tak! To powinna być zaakceptowana odpowiedź. Od MDN: developer.mozilla.org/en-US/docs/Web/API/…
Han


5

Wiem, że minęło 10 lat, odkąd zadano to pytanie, ale jeśli przewijałeś do tej pory, zakładam, że wciąż masz problem. Rozwiązanie Medera Omuraliewa jest najprostsze i może pomóc większości z nas, ale dla tych, którzy nie chcą mieć żadnych zobowiązań, oto:

  1. Użyj Param dla setTimeout
setTimeout(function(p){
//p == param1
},3000,param1);
  1. Użyj wyrażenia funkcji natychmiast wywołanego (IIFE)
let param1 = 'demon';
setTimeout(function(p){
    // p == 'demon'
},2000,(function(){
    return param1;
})()
);
  1. Rozwiązanie pytania
function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    setTimeout(postinsql,4000,(function(){
        return xmlhttp.responseText;
    })());
  }
}

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

4

Wiem, że jest stary, ale chciałem dodać do tego mój (preferowany) smak.

Myślę, że dość czytelnym sposobem na osiągnięcie tego jest przekazanie topicIddo funkcji, która z kolei używa argumentu do wewnętrznego odwoływania się do identyfikatora tematu. Ta wartość nie zmieni się, nawet jeśli topicIdna zewnątrz zostanie zmieniona wkrótce potem.

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

lub krótki:

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

4

Odpowiedź Davida Meistera wydaje się dbać o parametry, które mogą ulec zmianie natychmiast po wywołaniu setTimeout (), ale przed wywołaniem funkcji anonimowej. Ale jest to zbyt uciążliwe i niezbyt oczywiste. Odkryłem elegancki sposób robienia prawie tego samego przy użyciu IIFE (natychmiast wywołane wyrażenie funkcji).

W poniższym przykładzie currentListzmienna jest przekazywana do IIFE, który zapisuje ją w swoim zamknięciu, aż do wywołania funkcji opóźnionej. Nawet jeśli zmienna currentListzmieni się natychmiast po pokazanym kodzie, setInterval()zrobi to dobrze.

Bez tej techniki IIFE setTimeout()funkcja na pewno zostanie wywołana dla każdego h2elementu w DOM, ale wszystkie te wywołania będą widzieć tylko wartość tekstową ostatniego h2 elementu.

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

4

Ogólnie rzecz biorąc, jeśli chcesz przekazać funkcję jako wywołanie zwrotne z określonymi parametrami, możesz użyć funkcji wyższego rzędu. Jest to dość eleganckie w ES6:

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

setTimeout(someFunction(params), 1000);

Lub jeśli someFunctionjest to pierwsze zamówienie:

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

to jest bardzo niezgodne
151496

Rzeczywiście elegancki! Dzięki
Velojet,

3

Zauważ, że przyczyną topicId „nie zdefiniowano” w komunikacie o błędzie jest to, że istniała ona jako zmienna lokalna, gdy wykonano setTimeout, ale nie, kiedy nastąpiło opóźnione wywołanie postinsql. Zmienna żywotność jest szczególnie ważna, na którą należy zwrócić uwagę, szczególnie gdy próbujesz przekazać coś takiego jak odniesienie do obiektu.

Słyszałem, że możesz przekazać topicId jako trzeci parametr do funkcji setTimeout. Nie podano zbyt wielu szczegółów, ale mam wystarczającą ilość informacji, aby to zadziałało, a Safari działa. Nie wiem jednak, co oznaczają „błąd milisekundowy”. Sprawdź tutaj:

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


3

Jak rozwiązałem ten etap?

właśnie tak :

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

setTimeout czeka na odwołanie do funkcji, więc utworzyłem ją w zamknięciu, które interpretuje moje dane i zwraca funkcję z dobrym wystąpieniem moich danych!

Może uda ci się poprawić tę część:

_deepFunction(_deepData);

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

Przetestowałem go na Chrome, Firefox i IE i działa dobrze, nie wiem o wydajności, ale potrzebowałem, aby działała.

przykładowy test:

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

Może możesz zmienić podpis, aby był bardziej zgodny:

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

I wreszcie odpowiedź na pierwotne pytanie:

 myNass_setTimeOut( postinsql, 4000, topicId );

Mam nadzieję, że to może pomóc!

ps: przepraszam, ale angielski to nie jest mój język ojczysty!


Jest to zbyt skomplikowane w porównaniu do innych odpowiedzi.
Dan Dascalescu

3

działa to we wszystkich przeglądarkach (IE to nieparzysta)

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

3

jeśli chcesz przekazać zmienną jako parametr, spróbuj tego

jeśli wymagana jest funkcja i zmienna jako parmas, spróbuj tego

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

jeśli wymaganie jest zmiennymi tylko jako parametry, spróbuj tego

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

Możesz tego spróbować z ES5 i ES6


2

Możesz wypróbować domyślną funkcję „Apply ()” mniej więcej taką, możesz przekazać więcej argumentów jako wymaganie w tablicy

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

1

setTimeout jest częścią DOM zdefiniowaną przez WHAT WG.

https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html

Metoda, którą chcesz:

handle = self.setTimeout( handler [, timeout [, arguments... ] ] )

Planuje limit czasu, aby uruchomić moduł obsługi po upływie milisekund limitu czasu. Wszelkie argumenty są przekazywane bezpośrednio do modułu obsługi.

setTimeout(postinsql, 4000, topicId);

Najwyraźniej dodatkowe argumenty są obsługiwane w IE10. Alternatywnie możesz użyć setTimeout(postinsql.bind(null, topicId), 4000);, jednak przekazywanie dodatkowych argumentów jest prostsze i jest to preferowane.

Fakt historyczny: W czasach VBScript w JScript trzecim parametrem setTimeout był język jako ciąg znaków, domyślnie ustawiony na „JScript”, ale z opcją użycia „VBScript”. https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500(v%3Dvs.85)


0

@Jiri Vetyska dziękuje za post, ale w twoim przykładzie jest coś nie tak. Musiałem przekazać cel, który jest najechany (to), na funkcję przekroczenia limitu czasu i wypróbowałem twoje podejście. Testowany w IE9 - nie działa. Przeprowadziłem również badania i wydaje się, że jak wskazano tutaj, trzecim parametrem jest używany język skryptowy. Brak wzmianki o dodatkowych parametrach.

Postępowałem zgodnie z odpowiedzią @ meder i rozwiązałem problem z tym kodem:

$('.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
}

Mam nadzieję, że jest to przydatne dla kogoś innego.


0

Ponieważ istnieje problem z trzecim parametrem optonalnym w IE, a użycie zamknięć uniemożliwia nam zmianę zmiennych (na przykład w pętli) i nadal osiąganie pożądanego rezultatu, proponuję następujące rozwiązanie.

Możemy spróbować użyć takiej rekurencji:

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

Musimy upewnić się, że nic więcej nie zmienia tych zmiennych i że piszemy odpowiedni warunek rekurencji, aby uniknąć nieskończonej rekurencji.


0

// Oto trzy bardzo proste i zwięzłe odpowiedzi:

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

0

Odpowiedzi na pytanie, ale za pomocą prostej funkcji dodawania z 2 argumentami.

var x = 3, y = 4;

setTimeout(function(arg1, arg2) { 
      delayedSum(arg1, arg2);
}(x, y), 1000);

function delayedSum(param1, param2) {
     alert(param1 + param2); // 7
}

0

Musisz usunąć cudzysłowy z setTimeOutwywołania funkcji w następujący sposób:

setTimeout(postinsql(topicId),4000);

-1

Myślę, że chcesz:

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

1
Natrafiłem na przypadki, w których to po prostu nie działa (zawsze powoduje błąd „funkcja nieokreślona”), ale działa funkcja anonimowa. Co jest frustrujące, biorąc pod uwagę, że wszyscy twierdzą, że powyższa składnia powinna zawsze działać. (czy to możliwe, że jQuery jakoś przeszkadza metodzie „quote as string”?)
DA.

6
Załóżmy, że topicId jest funkcją ... Lub obiektem. To nie zadziała!
Serafeim

Jeśli naprawdę chcesz kontynuować tę metodę, użyj JSON.stringifyzwykłych obiektów i tablic, a następnie użyj JSON.parsefunkcji. Jednak wszystkie zachowania zostaną utracone, jeśli obiekt ma metody.
DarthCadeus,

-2

// Oto trzy bardzo proste i zwięzłe odpowiedzi:

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');
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.