Sen maszynopisu

150

Tworzę stronę internetową w Angular 2 przy użyciu Typescript i zastanawiałem się, czy istnieje sposób na zaimplementowanie thread.sleep(ms)funkcjonalności.

Moim przypadkiem jest przekierowanie użytkowników po przesłaniu formularza po kilku sekundach, co jest bardzo łatwe w html lub javascript, ale nie jestem pewien, jak to zrobić w Typescript.

Wielkie dzięki,

kha
źródło
8
Typescript to nadzbiór języka JavaScript. Więc napisz to w JavaScript i gotowe: masz rozwiązanie TypeScript.
JB Nizet

Odpowiedzi:

222

Musisz poczekać na TypeScript 2.0 z obsługą async/ awaitdla ES5, ponieważ jest teraz obsługiwany tylko dla kompilacji TS do ES6.

Byłbyś w stanie stworzyć funkcję opóźnienia z async:

function delay(ms: number) {
    return new Promise( resolve => setTimeout(resolve, ms) );
}

I nazwij to

await delay(300);

Należy pamiętać, że można używać awaittylko asyncfunkcji wewnętrznej .

Jeśli nie możesz ( powiedzmy, że budujesz aplikację nodejs ), po prostu umieść swój kod w asyncfunkcji anonimowej . Oto przykład:

    (async () => { 
        // Do something before delay
        console.log('before delay')

        await delay(1000);

        // Do something after
        console.log('after delay')
    })();

Przykładowa aplikacja TS: https://github.com/v-andrew/ts-template

W STARYM JS musisz używać

setTimeout(YourFunctionName, Milliseconds);

lub

setTimeout( () => { /*Your Code*/ }, Milliseconds );

Jednak każda większa przeglądarka obsługuje async/ awaitjest mniej przydatna.

Aktualizacja: TypeScript 2.1 jest tutaj z async/await.

Po prostu nie zapominaj, że potrzebujesz Promiseimplementacji podczas kompilacji do ES5, gdzie Promise nie jest natywnie dostępna.

PS

Musisz wyeksportować funkcję, jeśli chcesz jej używać poza oryginalnym plikiem.

v-andrew
źródło
1
Aktualizacja : obsługa async / await i generatorów dla ES5 / ES3 została przeniesiona do TypeScript 2.1
v-andrew
8
wydarzenie bez czekania, możesz zrobić opóźnienie (20000). potem (() => {
ZZZ
1
z jakiegoś powodu to nie zadziałało, await new Promise(resolve => setTimeout(resolve, 1000)).then(()=>console.log("fired"));ale zadziałałoawait new Promise(resolve => setTimeout(()=>resolve(), 1000)).then(()=>console.log("fired"));
fjch1997
@ fjch1997, opakuj go w asyncfunkcję. Dodałem przykład
v-andrew
2
Deklaracja funkcji 'delay' nie wymaga słowa kluczowego async, ponieważ już zwraca obietnicę.
SlavaSt
101

To działa: (dzięki komentarzom)

setTimeout(() => 
{
    this.router.navigate(['/']);
},
5000);
kha
źródło
1
Myślę, że dla uproszczenia ta odpowiedź powinna być już akceptowana.
Stefan Falk,
2
@StefanFalk Cześć Stefan. Przyjąłem drugą odpowiedź, ponieważ zawierała tę odpowiedź, a także posiadałem inne, bardziej "maszynowe" sposoby zrobienia opóźnienia, które mogą być interesujące dla innych. Osobiście używam tego w całym moim kodzie, ponieważ nie widzę żadnych korzyści z używania async / await do tego konkretnego zadania, ale nie jestem purystą TS i wybieram wszystko, co jest łatwiejsze / bardziej czytelne, więc zgadzam się z tobą zasadniczo :).
kha
Uderzyłem to. Czysty i skuteczny.
Travis L. Riffle
32

Z jakiegoś powodu powyższa zaakceptowana odpowiedź nie działa w nowych wersjach Angular (V6).

do tego użyj tego ...

async delay(ms: number) {
    await new Promise(resolve => setTimeout(()=>resolve(), ms)).then(()=>console.log("fired"));
}

powyżej pracował dla mnie.

Stosowanie:

this.delay(3000);

LUB dokładniejszy sposób

this.delay(3000).then(any=>{
     //your task after delay.
});
MarmiK
źródło
Po prostu zamień swoje „1000” na wywołanie parametru ms i byłoby idealnie.
greenskin
18

Z RxJS:

import { timer } from 'rxjs';

// ...

timer(your_delay_in_ms).subscribe(x => { your_action_code_here })

x wynosi 0.

Jeśli podasz drugi argument perioddo timer, nowa liczba będzie emitowana co periodmilisekundę (x = 0, a następnie x = 1, x = 2, ...).

Więcej informacji można znaleźć w oficjalnym dokumencie .

Qortex
źródło
3
Dzięki za tę perspektywę, przyszedłem tutaj, aby znaleźć „
widoczną
3
import { timer } from 'rxjs';

await timer(1000).pipe(take(1)).toPromise();

to działa lepiej dla mnie

FabioLux
źródło
Właściwość „take” nie istnieje w typie „Observable <number>”.
Anton Duzenko
import {take} z 'rxjs / operators';
FabioLux
@AntonDuzenko musisz to włożyć .pipe ()
Yohan Dahmani
2

Lub zamiast deklarować funkcję, po prostu:

setTimeout(() => {
    console.log('hello');
}, 1000);
Gebus
źródło
Dlaczego nie funkcja?
Naveen Kumar
1

Jeśli używasz angular5 i nowszych wersji, dołącz poniższą metodę do swojego pliku ts.

async delay(ms: number) {
    await new Promise(resolve => setTimeout(()=>resolve(), ms)).then(()=>console.log("fired"));
}

następnie wywołaj tę metodę delay () w dowolnym miejscu.

na przykład:

validateInputValues() {
    if (null == this.id|| this.id== "") {
        this.messageService.add(
            {severity: 'error', summary: 'ID is Required.'});
        this.delay(3000).then(any => {
            this.messageService.clear();
        });
    }
}

To zniknie warkot wiadomości po 3 sekundach.

Występ
źródło