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

Zeeshan Rang
źródło
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
2
wszystko jest jasne tutaj: w3schools.com/jsref/met_win_settimeout.asp
Vladislav
@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);
meder omuraliev
źródło
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:

Fabio Phms
źródło
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.

Jiri Vetyska
źródło
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.

David Meister
źródło
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.

David Sherret
źródło
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

dain
źródło
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 .

Schien
źródło
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.


źródło
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.

Russ Cam
źródło
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)
}
Jatin Verma
źródło
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);
}
Alpesh Patil
źródło
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);
Dominik
źródło
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>
Gurjeet Singh
źródło
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); 
John Hartman
źródło
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

pałka policjanta
źródło
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!

Anonimowy dzień
źródło
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);
użytkownik3756459
źródło
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

szalony człowiek
źródło
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);
Wisznu Prasanth G.
źródło
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)

Garrett
źródło
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.

Vladislav
źródło
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.

Vakhtang Tevdorashvili
źródło
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');
Bogaty
źródło
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
}
SridharKritha
źródło
0

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

setTimeout(postinsql(topicId),4000);
Ghanshyam Sharma
źródło
-1

Myślę, że chcesz:

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

źródło
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');
użytkownik11385739
źródło