Angular 4、如何延迟1秒更新[(ngModel)]
Angular 4, How to update [(ngModel)] with a delay of 1 seconds
由于 ngModel 正在立即更新如何延迟。
<input type="text" value="{{item.task_name}}" name="task_name" [(ngModel)]="item.task_name" (ngModelChange)="update_fields([item.task_name])" >
我需要通过调用 update_fields() 延迟一秒来保存 task_name ,以避免立即调用服务。
谢谢
update_fields(){
this.service.yourTask(){
.subscribe(data => {
setTimeout(()=>{ //your task }, 4000)
}
}
}
someFunction() {
setTimeout(() => /* code to execute */, 3000)
}
Rxjs 和 Observables 是此类任务的完美候选者!这是如何实现的示例:
模板:
<input type="text" [value]="item.task_name"(keyup)="term$.next($event.target.value)">
分量:
import ......
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
@Component{(
...
)}
export class YourComponent {
term$ = new Subject<string>();
constructor() {
this.term$
.debounceTime(1000)
.distinctUntilChanged()
.switchMap(term => /*do something*/);
}
}
subject
是一种既可作为可观察对象又可作为观察者的对象 - 这意味着您可以订阅它并从中发出值(使用 next()
)!
debounceTime
等待以毫秒为单位的提供时间,直到它允许新的更改
distinctUntilChanges
不允许同一个输入连续通过两次
switchMap
从链中获取最新的可观察值,因此您不会一次获得多个结果
这是一个适用于回调的解决方案。
查看模板:
<input ... #element (ngModelChange)="delayAction(element, doSomething, [$event])">
组件class:
actionsByElements = new Map<HTMLElement, Subscription>();
delayAction(element: HTMLElement, cb: Function, args: any[]) {
// cancel countdown by element
let action = this.actionsByElements.get(element);
if(action) {
action.unsubscribe();
}
// start new countdown by element
action = timer(1000).subscribe(() => cb.apply(this, args));
this.actionsByElements.set(element, action);
}
doSomething(){...}
Fredrik Lundin 的回答已更新 Angular 6:
模板:
<input type="text" [value]="item.task_name" (keyup)="term$.next($event.target.value)">
分量:
import ......
import { Subject, EMPTY } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
@Component{(
...
)}
export class YourComponent implements OnDestroy {
term$ = new Subject<string>();
private searchSubscription: Subscription;
constructor() {
this.searchSubscription = this.term$.pipe(
debounceTime(1000),
distinctUntilChanged(),
switchMap(term => {
/*do something*/
return EMPTY;
})
).subscribe();
}
ngOnDestroy() {
//remember to unsubscribe on destroy
if (this.searchSubscription) {
this.searchSubscription.unsubscribe();
this.searchSubscription = null;
}
}
}
很多解决方案使用setTimeout()
,但这会导致每次模型更改时都调用该函数,一个简单的防止方法是先清除超时
例如
timeOut;
timeOutDuration = 1000;
update_fields(data) {
clearTimeout(this.timeOut);
this.timeOut = setTimeout(() => {
//do something
}, this.timeOutDuration);
}
这只会在最后一次更新完成并且 timeOutDuration
已过
后调用该函数一次
由于 ngModel 正在立即更新如何延迟。
<input type="text" value="{{item.task_name}}" name="task_name" [(ngModel)]="item.task_name" (ngModelChange)="update_fields([item.task_name])" >
我需要通过调用 update_fields() 延迟一秒来保存 task_name ,以避免立即调用服务。
谢谢
update_fields(){
this.service.yourTask(){
.subscribe(data => {
setTimeout(()=>{ //your task }, 4000)
}
}
}
someFunction() {
setTimeout(() => /* code to execute */, 3000)
}
Rxjs 和 Observables 是此类任务的完美候选者!这是如何实现的示例:
模板:
<input type="text" [value]="item.task_name"(keyup)="term$.next($event.target.value)">
分量:
import ......
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
@Component{(
...
)}
export class YourComponent {
term$ = new Subject<string>();
constructor() {
this.term$
.debounceTime(1000)
.distinctUntilChanged()
.switchMap(term => /*do something*/);
}
}
subject
是一种既可作为可观察对象又可作为观察者的对象 - 这意味着您可以订阅它并从中发出值(使用 next()
)!
debounceTime
等待以毫秒为单位的提供时间,直到它允许新的更改
distinctUntilChanges
不允许同一个输入连续通过两次
switchMap
从链中获取最新的可观察值,因此您不会一次获得多个结果
这是一个适用于回调的解决方案。
查看模板:
<input ... #element (ngModelChange)="delayAction(element, doSomething, [$event])">
组件class:
actionsByElements = new Map<HTMLElement, Subscription>();
delayAction(element: HTMLElement, cb: Function, args: any[]) {
// cancel countdown by element
let action = this.actionsByElements.get(element);
if(action) {
action.unsubscribe();
}
// start new countdown by element
action = timer(1000).subscribe(() => cb.apply(this, args));
this.actionsByElements.set(element, action);
}
doSomething(){...}
Fredrik Lundin 的回答已更新 Angular 6:
模板:
<input type="text" [value]="item.task_name" (keyup)="term$.next($event.target.value)">
分量:
import ......
import { Subject, EMPTY } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
@Component{(
...
)}
export class YourComponent implements OnDestroy {
term$ = new Subject<string>();
private searchSubscription: Subscription;
constructor() {
this.searchSubscription = this.term$.pipe(
debounceTime(1000),
distinctUntilChanged(),
switchMap(term => {
/*do something*/
return EMPTY;
})
).subscribe();
}
ngOnDestroy() {
//remember to unsubscribe on destroy
if (this.searchSubscription) {
this.searchSubscription.unsubscribe();
this.searchSubscription = null;
}
}
}
很多解决方案使用setTimeout()
,但这会导致每次模型更改时都调用该函数,一个简单的防止方法是先清除超时
例如
timeOut;
timeOutDuration = 1000;
update_fields(data) {
clearTimeout(this.timeOut);
this.timeOut = setTimeout(() => {
//do something
}, this.timeOutDuration);
}
这只会在最后一次更新完成并且 timeOutDuration
已过