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 topicId
nie 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ć?
javascript
parameters
callback
settimeout
Zeeshan Rang
źródło
źródło
Odpowiedzi:
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()
lubsetInterval()
, 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:
źródło
window.setTimeout
jest 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óźnionaeval()
.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:
Więcej szczegółów:
źródło
Po przeprowadzeniu pewnych badań i testów jedyną poprawną implementacją jest:
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.
źródło
var that = this; setTimeout( function() { that.foo(); }, 1000);
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 :
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.
źródło
Niedawno natknąłem się na wyjątkowej sytuacji konieczności użyć
setTimeout
w pętli . Zrozumienie tego może pomóc ci zrozumieć, jak przekazać parametrysetTimeout
.Metoda 1
Użyj
forEach
iObject.keys
, zgodnie z sugestią Sukimy :Polecam tę metodę.
Metoda 2
Użyj
bind
:JSFiddle: http://jsfiddle.net/MsBkW/
Metoda 3
Lub jeśli nie możesz użyć
forEach
lubbind
, użyj IIFE :Metoda 4
Ale jeśli nie zależy ci na IE <10, możesz skorzystać z sugestii Fabio :
Metoda 5 (ES6)
Użyj zmiennej o zasięgu blokowym:
Chociaż nadal polecam używanie
Object.keys
zforEach
ES6.źródło
.bind
nie 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ązaniubind
to także w środowisku, które oferujeObject.keys
iforEach
. 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).async
bibliotekę ( 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 asynchronicznychforEach
,map
,reduce
, itd.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 ustawieniathis
kontekstu):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
źródło
setTimeout(postinsql.bind(this, topicId), 4000);
bind
. To naprawdę tworzy czytelny kod.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:
Niektórzy sugerują użycie funkcji anonimowej podczas wywoływania funkcji limitu czasu:
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 .
źródło
Moja odpowiedź:
Wyjaśnienie:
LUB
Zasadniczo konwertuje się na:
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
topicId
zmianie, zmienia się również wartość limitu czasu. Naprawił go klonZastąpić
z
lub jeszcze lepiej, zamień wyrażenie łańcuchowe na anonimową funkcję
EDYTOWAĆ:
Komentarz Brownstone'a jest niepoprawny, będzie działał zgodnie z przeznaczeniem, jak pokazano, uruchamiając to w konsoli Firebug
Zauważ, że zgadzam się z innymi, że powinieneś unikać przekazywania ciągu znaków,
setTimeout
ponieważ spowoduje to wywołanieeval()
ciągu i przekazanie funkcji.źródło
Możesz przekazać parametr do funkcji zwrotnej setTimeout jako:
setTimeout (funkcja, milisekundy, param1, param2, ...)
na przykład.
źródło
setTimeout( (p) => { console.log(p); }, 1000, "hi" );
Najłatwiejsze rozwiązanie dla różnych przeglądarek do obsługi parametrów w setTimeout:
Jeśli nie masz nic przeciwko nieobsługiwaniu IE 9 i niższych wersji:
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
źródło
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:
źródło
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
topicId
do funkcji, która z kolei używa argumentu do wewnętrznego odwoływania się do identyfikatora tematu. Ta wartość nie zmieni się, nawet jeślitopicId
na zewnątrz zostanie zmieniona wkrótce potem.lub krótki:
źródło
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
currentList
zmienna jest przekazywana do IIFE, który zapisuje ją w swoim zamknięciu, aż do wywołania funkcji opóźnionej. Nawet jeśli zmiennacurrentList
zmieni się natychmiast po pokazanym kodzie,setInterval()
zrobi to dobrze.Bez tej techniki IIFE
setTimeout()
funkcja na pewno zostanie wywołana dla każdegoh2
elementu w DOM, ale wszystkie te wywołania będą widzieć tylko wartość tekstową ostatniegoh2
elementu.źródło
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:
Lub jeśli
someFunction
jest to pierwsze zamówienie:źródło
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
źródło
Jak rozwiązałem ten etap?
właśnie tak :
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ęść:
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:
Może możesz zmienić podpis, aby był bardziej zgodny:
I wreszcie odpowiedź na pierwotne pytanie:
Mam nadzieję, że to może pomóc!
ps: przepraszam, ale angielski to nie jest mój język ojczysty!
źródło
działa to we wszystkich przeglądarkach (IE to nieparzysta)
źródło
jeśli chcesz przekazać zmienną jako parametr, spróbuj tego
jeśli wymagana jest funkcja i zmienna jako parmas, spróbuj tego
jeśli wymaganie jest zmiennymi tylko jako parametry, spróbuj tego
Możesz tego spróbować z ES5 i ES6
źródło
Możesz wypróbować domyślną funkcję „Apply ()” mniej więcej taką, możesz przekazać więcej argumentów jako wymaganie w tablicy
źródło
setTimeout jest częścią DOM zdefiniowaną przez WHAT WG.
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html
Metoda, którą chcesz:
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)
źródło
@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:
Mam nadzieję, że jest to przydatne dla kogoś innego.
źródło
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:
Musimy upewnić się, że nic więcej nie zmienia tych zmiennych i że piszemy odpowiedni warunek rekurencji, aby uniknąć nieskończonej rekurencji.
źródło
// Oto trzy bardzo proste i zwięzłe odpowiedzi:
źródło
Odpowiedzi na pytanie, ale za pomocą prostej funkcji dodawania z 2 argumentami.
źródło
Musisz usunąć cudzysłowy z
setTimeOut
wywołania funkcji w następujący sposób:źródło
Myślę, że chcesz:
źródło
JSON.stringify
zwykłych obiektów i tablic, a następnie użyjJSON.parse
funkcji. Jednak wszystkie zachowania zostaną utracone, jeśli obiekt ma metody.// Oto trzy bardzo proste i zwięzłe odpowiedzi:
źródło