I'm trying to abstract away a data load function that uses promises, but now I'm unsure how to call that function from another module... :(
dataservice module
export default class DataService {
loadStudents() {
return window.fetch("data.json")
.then(res => res.json())
.then(res => {
// I want to return the result not a promise?
return res
})
}
}
main app module
import DataService from "../classes/dataservice"
const ds = new DataService()
ds.loadStudents().then(res => {
// here I just want the data, not a promise...
console.log(res)
})
I got this function in one of my servlets:
private setValues() {
this.config.socket.on('config.weather', (values:any) => {
console.log(values);
}
I want to outsource so I get something like this:
private setValues() {
this.config.load('weather').then((values:any) => {
console.log(values);
}
any in the socket Service:
public load(key: string) {
return new Promise(resolve => {
this.socket.on('config.' + key, values => resolve(values));
});
This works for the first call, but when the socket fires again it wont be send to the setValues() function because a Promise only works once.
I think I have to use an Observable, but I have no Idea where to place it.
I used a subject and now everything works fine:
public load(key: string) {
let sub = new Subject();
this.socket.on('config.' + key, values => {
sub.next(values);
});
return sub;
}
and
private setValues() {
this.config.load('weather').subscribe((values:any) => {
console.log(values);
}
i'm new to typescript and i can't find an alternative to optimize a line of code as you can see below. I need to filter an array derived from a callback function that i pass to a promise.then()...
getAllItems(): Promise<MyItem[]> {
return this.http.get(this.itemsUrl).toPromise()
.then(this.extractData)
.catch(this.handleError);
}
getItem(id: number | string): Promise<MyItem> {
var that = this; // i want to avoid to use this...
return this.http.get(this.itemsUrl).toPromise()
// ...just here
.then(function(res) {
return that.extractData(res).filter(h => h.id === +id)[0];
})
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
Code above works well but i want to use a more short(more typescript i guess) syntax to achieve something like:
getItem(id: number | string): Promise<MyItem> {
return this.http.get(this.itemsUrl).toPromise()
// ... here again
.then(this.extractData => result.filter(h => h.id === +id)[0])
.catch(this.handleError);
}
obviously it does not work...any suggestion please? Thanks.
You still have to pass the response to your extractData method:
getItem(id: number | string): Promise<MyItem> {
return this.http.get(this.itemsUrl).toPromise()
// ... here again
.then(res => this.extractData(res).filter(h => h.id === +id)[0])
.catch(this.handleError);
}
I'd like to hit and display every 5 seconds from a http link, and it seems to be that using angular2, an observable would be the way to go?
getPhaseVotes(issue: string) {
return this.http.get(this.URL + 'issue/' + issue + '/getPhaseVotes')
.subscribe(data => this.phase_votes = data.json(),
err => console.log(err),
() => this.getStatus(issue));
}
How should I be updating this every 5 seconds?
You could use the interval operator of Observable:
#Injeactable()
export class SomeService {
constructor(private http:Http) {}
getPhaseVotes(issue: string) {
return Observable.interval(5000).flatMap(() => {
return this.http.get(this.URL + 'issue/' + issue + '/getPhaseVotes')
.map(res => res.json());
});
}
}
This way you need to call once the getPhaseVotes method and subscribe on it. Every 5 seconds, an HTTP request will be executed transparently and the result provided within the subscribed callback:
#Component({
(...)
})
export class SomeComponent {
constructor(private service:SomeService) {
this.service.getPhaseVotes('someissue')
.subscribe(data => this.phase_votes = data,
err => console.log(err),
() => this.getStatus(issue));
}
}
This article could give you more hints in its "Polling" section:
https://jaxenter.com/reactive-programming-http-and-angular-2-124560.html
I'm building an app to get some events from facebook, take a look:
EventComponent:
events: Object[] = [];
constructor(private eventService: EventService) {
this.eventService.getAll()
.subscribe(events => this.events = events)
}
EventService:
getAll() {
const accessToken = 'xxxxxxxxxxx';
const batch = [{...},{...},{...},...];
const body = `access_token=${accessToken}&batch=${JSON.stringify(batch)}`;
return this.http.post('https://graph.facebook.com', body)
.retry(3)
.map(response => response.json())
}
AuthenticationService:
getAccessToken() {
return new Promise((resolve: (response: any) => void, reject: (error: any) => void) => {
facebookConnectPlugin.getAccessToken(
token => resolve(token),
error => reject(error)
);
});
}
I have a few questions:
1) How can I set an interval to update the events every 60 seconds?
2) The value of accessToken will actually come from a promise, should I do something like this?
getAll() {
const batch = [{...},{...},{...},...];
this.authenticationService.getAccessToken().then(
accessToken => {
const body = `access_token=${accessToken}&batch=${JSON.stringify(batch)}`;
return this.http.post('https://graph.facebook.com', body)
.retry(3)
.map(response => response.json())
},
error => {}
);
}
3) If yes, how can I also handle errors from the getAccessToken() promise since I'm returning just the Observer?
4) The response from the post request will not return an array of objects by default, I'll have to make some manipulation. Should I do something like this?
return this.http.post('https://graph.facebook.com', body)
.retry(3)
.map(response => response.json())
.map(response => {
const events: Object[] = [];
// Manipulate response and push to events...
return events;
})
Here are the answers to your questions:
1) You can leverage the interval function of observables:
getAll() {
const accessToken = 'xxxxxxxxxxx';
const batch = [{...},{...},{...},...];
const body = `access_token=${accessToken}&batch=${JSON.stringify(batch)}`;
return Observable.interval(60000).flatMap(() => {
return this.http.post('https://graph.facebook.com', body)
.retry(3)
.map(response => response.json());
});
}
2) You could leverage at this level the fromPromise function of observables:
getAll() {
const batch = [{...},{...},{...},...];
return Observable.fromPromise(this.authenticationService.getAccessToken())
.flatMap(accessToken => {
const body = `access_token=${accessToken}&batch=${JSON.stringify(batch)}`;
return this.http.post('https://graph.facebook.com', body)
.retry(3)
.map(response => response.json())
});
}
3) You can leverage the catch operator to handle errors:
getAll() {
const batch = [{...},{...},{...},...];
return Observable.fromPromise(this.authenticationService.getAccessToken())
.catch(() => Observable.of({})) // <-----
.flatMap(accessToken => {
const body = `access_token=${accessToken}&batch=${JSON.stringify(batch)}`;
return this.http.post('https://graph.facebook.com', body)
.retry(3)
.map(response => response.json())
});
}
In this case, when an error occurs to get the access token, an empty object is provided to build the POST request.
4) Yes sure! The map operator allows you to return what you want...
Put the event inside a timeout block and set the interval of 60s. setTimeout(() => {},60000).
Using Template string is totally fine but you're telling its value comes from a promise. If your whole block of code is inside resolve function of promise this should fine. So it depends on where your code is. And why promises .In A2 it's recommended to use Observables and not promises. Don't mix them.
You're not returning anything in the error function. So if you return error from that block you'll get error data in case of error. error => erroror error => { return error; }.
Exactly you should you map to get the response and manipulate it and return just the array from that function. .map(resp => { return resp.array}). Since respons is in JSON format now you have to get array from it and return it. you can do as much modifications you want before returning it.
Feel free to edit the answer...