Angular 4 setTimeout не ждет
Я создаю приложение angular 4 с typescript.
У меня есть функция, которая должна выполняться каждые 10 секунд до указанного условия остановки. Я создал цикл с некоторым тестовым кодом, используя setTimeout, чтобы узнать, будет ли он работать.
Мой тестовый код:
public run() {
let i = 0;
while (i < 4) {
setTimeout(this.timer,3000);
i++;
}
}
public timer(){
console.log("done")
}
Однако это, кажется, ждет 3 секунды, или браузер просто медленный...
а затем распечатывается 4 раза. Таким образом, код не работает. Я делаю это неправильно или есть другие возможности делать такие вещи?
Ответы
Ответ 1
Поскольку вы используете Angular, вы можете сделать это гораздо проще, используя takeWhile
:
Observable.interval(10000)
.takeWhile(() => !stopCondition)
.subscribe(i => {
// This will be called every 10 seconds until `stopCondition` flag is set to true
})
Ответ 2
Да, вы делаете это неправильно: у вас есть цикл, говорящий 4 раза подряд, чтобы выполнить timer()
через 3 секунды, начиная с этого момента.
Чтобы делать то, что вы хотите, вам придется перепланировать следующий таймер каждый раз, когда вызывается timer()
, или, проще, использовать setInterval()
:
let count = 0;
const interval = window.setInterval(() => {
this.timer();
count++;
if (count >= 4) {
window.clearInterval(interval);
}
}, 3000);
Обратите внимание, что поскольку вы используете angular, использование наблюдаемых будет намного проще:
Observable.interval(3000).take(4).subscribe(() => this.timer());
Ответ 3
Я сделал это с Angular 6. Этот код запрашивает каждые 5 секунд, чтобы получить прогресс рендеринга. Он остановит отправку запроса, когда прогресс достигнет 100%.
import {interval} from "rxjs";
getProgress(searchId): void{
const subscription = interval(5000)
.subscribe(()=>{
//Get progress status from the service every 5 seconds
this.appService.getProgressStatus(searchId)
.subscribe((jsonResult:any)=>{
//update the progress on UI
//cancel subscribe until it reaches %100
if(progressPercentage === 100)
subscription.unsubscribe();
},
error => {
//show errors
}
);
});
}
Ответ 4
Это действительно не способ использовать метод async
. Цикл while
проходит 4 раза за один раз и запускает 4 таймера. Который будет выводить одновременно и через 3 секунды. Однако вы можете использовать функциональность await
и async
из TypeScript:
public stopCondition: boolean = false;
public async run(): Promise<void> {
while (!this.stopCondition) {
await new Promise<void>(resolve => {
setTimeout(resolve, 10000);
});
this.execute();
}
console.log('done');
}
public execute(): void {
if ('whatever should trigger your stop condition') {
this.stopCondition = true;
}
}
Это будет запускать метод execute
через каждые 10 секунд, пока stopCondition === false
. Когда stopCondition === true
будет выводить done
.
Ответ 5
Используйте функцию setInterval(hander:(args:any[]),ms:Number,args:any[])
, которая является одним из методов OnInit
.
setInterval(a=>{
alert("yes....");
},10000,[]);
Появится предупреждение "да" через 10 секунд.
Ответ 6
Да, это правильное поведение. У вас синхронный цикл, который создал 4 задержанных действия и завершает этот цикл. Это происходит за несколько миллисекунд. Таким образом, все 4 задержанных действия регистрируются для запуска через 3 секунды примерно в то же время.
Итак, через 3 секунды вы получите все 4 ответа от этих отложенных действий.
Если вы хотите иметь выполнение вызова последствий (сначала через 3 секунды, затем второй после первого), рассмотрите возможность использования promises для этого и вызовите новое обещание с 3-секундной задержкой после предыдущего завершения.
fisrtPromise
.then(secondPromise)
.then(thirdPromise);
https://developer.mozilla.org/uk/docs/Web/JavaScript/Reference/Global_Objects/Promise
Ответ 7
Поскольку вы вызываете setTimeout внутри цикла while, и из-за асинхронного выполнения операторов он не будет ждать выполнения функции Timer перед тем, как перейти к следующей итерации. Вы можете достичь требуемой функциональности, используя приведенный ниже код
public run() {
var i = 0;
var interval = setInterval(() => {
if (++i === 4) {
clearInterval(interval);
}
else {
this.timer();
}
}, 3000);
}
public timer() {
console.log("done")
}