William Grasel PRO
Desenvolvedor Web, Google Developer Expert, Microsoft Most Valuable Professional, palestrante, consultor e coordenador do AngularSP.
@willgmbr
fb.me/wgrasel
The ReactiveX library for JavaScript.
[1, 2, 3]
.map(i => i * 2) // [2, 4, 6]
.filter(i => i > 5) // [6]
.concat([10, 20, 30]) // [6, 10, 20, 30]
Observable.of(1, 2, 3)
.map(i => i * 2)
.filter(i => i > 5)
.concat(
Observable.of(10, 20, 30)
)
Observable.fromEvent(document, 'click')
.map(i => i * 2)
.filter(i => i > 5)
.concat(
Observable.fromEvent(document, 'blur')
)
Observable.from(function* (){ yield 9; })
.map(i => i * 2)
.filter(i => i > 5)
.concat(
Observable.from([10, 20, 30])
)
.subscribe(console.log)
Array.of(1, 2, 3)
.map(i => i * 2)
.filter(i => i > 5)
.concat(
Array.of(10, 20, 30)
)
Observable.interval(500)
.map(i => i * 2)
.filter(i => i > 5)
.concat(
Observable.of(10, 20, 30)
)
Observable.from(function* (){ yield 9; })
.map(i => i * 2)
.filter(i => i > 5)
.concat(
Observable.from([10, 20, 30])
)
<input type="text" [(ngModel)]="myInput">
<ul>
<li *ngFor="let r of results">{{r.name}}</li>
</ul>
<input type="text" [formControl]="myInput">
<ul>
<li *ngFor="let r of results">{{r.name}}</li>
</ul>
<input type="text" [formControl]="myInput">
<ul>
<li *ngFor="let r of results | async">{{r.name}}</li>
</ul>
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([]);
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([])
.merge(this.myInput.valueChanges);
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([])
.merge(this.myInput.valueChanges)
.map(v => `https://swapi.co/api/people/?search=${v}`);
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([])
.merge(this.myInput.valueChanges)
.map(v => `https://swapi.co/api/people/?search=${v}`)
.mergeMap(url => this.http.get(url));
constructor(private http: HttpClient) {}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([])
.merge(this.myInput.valueChanges)
.map(v => `https://swapi.co/api/people/?search=${v}`)
.switchMap(url => this.http.get(url))
.map(json => json['results']);
constructor(private http: HttpClient) {}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([])
.merge(this.myInput.valueChanges)
.filter(v => v.length > 2)
.map(v => `https://swapi.co/api/people/?search=${v}`)
.switchMap(url => this.http.get(url))
.map(json => json['results']);
constructor(private http: HttpClient) {}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([])
.merge(this.myInput.valueChanges)
.filter(v => v.length > 2)
.debounceTime(300)
.map(v => `https://swapi.co/api/people/?search=${v}`)
.switchMap(url => this.http.get(url))
.map(json => json['results']);
constructor(private http: HttpClient) {}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([])
.merge(this.myInput.valueChanges)
.map(v => `https://swapi.co/api/people/?search=${v}`)
.mergeMap(url => this.http.get(url))
.map(json => json['results']);
constructor(private http: HttpClient) {}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myInput = new FormControl;
results = Observable.of([])
.merge(this.myInput.valueChanges)
.filter(v => v.length > 2)
.debounceTime(300)
.map(v => `https://swapi.co/api/people/?search=${v}`)
.switchMap(url => this.http.get(url))
.map(json => json['results'])
.retry(3);
constructor(private http: HttpClient) {}
}
@Component()
export class UserAddressComponent {
constructor (
user: UserService,
address: AddressService,
) {
user.getCurrentUser().subscribe(user => {
})
}
}
@Component()
export class UserAddressComponent {
constructor (
user: UserService,
address: AddressService,
) {
user.getCurrentUser().pipe(
).subscribe(user => {
this.address = address;
})
}
}
@Component()
export class UserAddressComponent {
constructor (
user: UserService,
address: AddressService,
) {
user.getCurrentUser().subscribe(user => {
address.getAddressFromUser(user).subscribe(address => {
this.address = address;
})
})
}
}
@Component()
export class UserAddressComponent {
constructor (
user: UserService,
address: AddressService,
) {
user.getCurrentUser().pipe(
mergeMap(user => this.address.getAddressFrom(user))
).subscribe(address => {
this.address = address;
})
}
}
@Component()
export class MyComponent {
ngOnInit() {
interval(1000)
.subscribe(i => console.log(i));
}
}
@Component()
export class MyComponent {
unsubscribe = new Subject();
ngOnInit() {
interval(1000)
.subscribe(i => console.log(i));
}
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
}
@Component()
export class MyComponent {
unsubscribe = new Subject();
ngOnInit() {
interval(1000)
.pipe(takeUntil(this.unsubscribe))
.subscribe(i => console.log(i));
}
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
}
FOWLER, Martin. 2005
FOWLER, Martin. 2011
RxJS powered side effect model
Compose and cancel async actions to create side effects and more.
By William Grasel
Programação reativa no mundo do Front End não é sobre usar um framework ou outro, é sobre como estruturar seu código e toda sua arquitetura de modo que esse paradigma faça sentido. Quem já brincou com qualquer implementação do ReactiveX sabe que é muito fácil dar um nó nas nossas cabeças, sem saber como estruturar os stream de modo que tudo se encaixem corretamente, ou mesmo sem encontrar o operador ideal para cada situação. Essa não é uma palestra introdutória ao tema, essa é uma palestra para ajudar aqueles que já queimaram muitos neurônios e querem melhorar seus skills com exemplos práticos.
Desenvolvedor Web, Google Developer Expert, Microsoft Most Valuable Professional, palestrante, consultor e coordenador do AngularSP.