I have some old code which does ajax calls. I wrote a new angular 10 application, which needs to run the original ajax code directly into the angular service (per requirement). Is there a way to run an ajax call directly or a node module that can be used. Thanks for the help.
#Injectable({providedIn: 'root'})
export class SomeService {
destroy$ = new Subject();
constructor(private http: HttpClient) { }
ajax(): Observable<DataType> {
return this.http
.get<DataType>(URL, {params: {email: 'tt#tt.tt'}})
.pipe(
takeUntil(this.destroy$), // will unsubscribe automatically if call this.destroy$.next(true) && this.destroy$.complete()
map(data => /*map data here if need*/)
);
}
}
Related
I am trying to use a DataService property myData that is waiting for callback. But it is undefined when I call in DataComponent. How can I access and use it there?
export class DataService {
public myData;
constructor(private http: HttpClient) {
this.load().then((data) => {
this.myData = data
})
}
load() {
return new Promise((resolve) => {
this.http.get('https://reqres.in/api/users').subscribe(
(res: any) => {
console.log(res.data)
resolve(res.data)
},
(error) => {
console.log(error);
}
)
})
}
}
export class DataComponent implements OnInit {
constructor(private dataService: DataService) {
this.prepareData();
}
prepareData() {
console.log(this.dataService.myData)
}
ngOnInit(): void {
}
}
Here is the source code: https://stackblitz.com/edit/angular-ivy-kbpdpo
You are running into a race condition since this is an asynchronous function.
This change works: https://stackblitz.com/edit/angular-ivy-vf3llg
Consider reading up on https://angular.io/guide/http
Personally, I just have services return raw data and manipulate it elsewhere, but if needed you can tap into the response as I have shown i the updated example.
This question and answer are probably really a duplicate of this question...
What are pipe and tap methods in Angular tutorial?
your load() method is asynchronous, that means that it can return the response after 2 hours, so it will execute your callback after 2 hours, and you are asking myData synchronously which means that you are asking it right now, so it won't work.
you have to wait until the answer is returned, in your code there is no chance to accomplish this, so either remove yourData field and just subscribe it into the component, or create BehaviorSubject and emit value to the component
Hi I am developing a web app which makes frequent get calls to a remote API. The response from the calls will always be the same so to speed up the performance of the site, I want to save the response in a JSON file locally so that the get requests are only called whenever the json file is empty.
You can not save JSON data to local file and load data because of security reason.
You can use localStorage or sessionStorage to save JSON object.
#Injectable()
export class YourService{
constructor(private http: HttpClient){
}
getData(){
var cached = JSON.parse(localStorage.setItem('yourkey'));
if(cached == null || cached == undefined){
this.http.get('yoururl').subscribe(data=>{
localStorage.setItem('yourkey', JSON.stringify(data);
return data;
});
}else{
return cached;
}
}
}
I have written a library called ngx-rxcache which is exactly for this sort of thing.
https://github.com/adriandavidbrand/ngx-rxcache
I have written an article on it here https://medium.com/#adrianbrand/angular-state-management-with-rxcache-468a865fc3fb
#Injectable()
export class DataService{
get data$(): Observable<DataType> {
return this.dataCache.value$;
}
private dataCache = this.cache.get<DataType>({
id: 'some unique identifer',
construct: () => this.http.get<DataType>('/dataUrl'),
autoload: true
});
constructor(private http: HttpClient, private cache: RxCacheService) {}
}
and in a component use the data$ observable
data$ = this.dataService.data$;
and in the template use the async pipe.
{{ data$ | async }}
I am working on an Angular4 app.
Here is a service I am using to get the data-
export class BookingService {
constructor(private http: HttpClient) {}
getMemberBookings(memberID: number): Observable<any> {
return this.http.get('http://myapi.com/bookings/member/'+memberID).map(response => response['bookings']);
}
}
And then in my component-
export class PrintButtonComponent implements OnInit {
bookings: any;
constructor(private service: BookingService) {}
ngOnInit() {}
downloadPDF() {
this.getBookings(memberID);
//pdf creation logic
}
getBookings(memberID: number) {
this.service.getMemberBookings(memberID).subscribe(data => this.bookings = data);
}
}
The problem is I want to use the data from the service in the downloadPDF method as there is other data in it that will be needed to create the PDF.
But when I return the data from the subscribe or set it to a property, it is giving undefined. I understand that this is due to asynchronous nature, but I dont want to put my pdf creation logic inside the subscribe method.
So how do I solve this problem? I am quite new to Angular and observables.
Thank you.
Since the code above doesn't involve multiple values per observable and doesn't require to stick to them, this can be done with async..await with no extra nesting:
async downloadPDF() {
await this.getBookings(memberID);
//pdf creation logic
}
async getBookings(memberID: number) {
this.bookings = await this.service.getMemberBookings(memberID).toPromise();
}
As any other RxJS operator, toPromise has to be imported.
I want to be able to instantiate a model class, but also give it access to services.
For example, say I have these endpoints:
/book/:id
/book/:id/author
I want to have a BooksService service to fetch a list a Book instance. I'd like the book instances to be instantiated with new, given a definition JSON through the constructor, while still being able to use Angular dependencies.
Example of what I want to do:
BooksService.getBook(1) // makes call to /book/1
.subscribe((book) => {
book.getAuthor() // makes call to /book/1/author
...
});
To accomplish this, I tried to use a factory to new an instance of a book model. I then pass in a reference to the Http injected dependency that the factory injects.
Here's what I have:
BooksService
#Injectable()
export class BookService {
constructor(
private http: Http,
private bookModelFactory: BookModelFactory
) {}
getBook(): Observable<BookModel> {
return this.http.get('http://localhost:3000/book/1')
.map((res) => {
return this.bookModelFactory.make(res.json().data);
});
}
}
BookModel, BookModelFactory
#Injectable()
export class BookModelFactory {
constructor (private http: Http) {}
make(def: object): BookModel {
var book = new BookModel(def);
book.http = this.http;
return book;
}
}
export class BookModel {
def: any;
http: Http;
constructor (def: object) {
this.def = def;
}
getAuthor() {
console.log('http', this.http);
this.http.get('http://localhost:3000/book/1/author');
}
}
When I try to use this code, I see the console log for the http object in book.getAuthor(). It exists, and I can see the get method on it. But it never makes the API request. Nothing in the network tab has anything about a call to /book/1/author. There are no errors. Simply put, nothing happens.
Why isn't the request being made when this.http.get('...') is being called in getAuthors()?
Thanks in advance.
Using Angular 4.
(Imports statements are removed for brevity)
2) If this is a good strategy... why isn't the request being made when this.http.get('...') is being called in getAuthors()?
Because no-one ever subscribed to the results of this call:
this.http.get('http://localhost:3000/book/1/author').subscribe(res => {
// do something with the results here
});
In angular if you do not subscribe to the results of the HTTP call, then this call will never be made.
Or maybe you want your getAuthor method to return an Observable<Author> so that it is the caller of this method that can subscribe to the results:
getAuthor(): Observable<Author> {
return this.http.get('http://localhost:3000/book/1/author').map(res => {
return res.json().data;
});
}
So that you can subscribe to it later:
BooksService.getBook(1) // makes call to /book/1
.subscribe(book => {
book.getAuthor() // makes call to /book/1/author
.subscribe(author => {
// do something with the book author here
});
...
});
So remember, if you do not subscribe, the AJAX call will not be made.
When writing services in TypeScript for AngularJS do you define a model for the request and the response?
So for example, given the following service call into a RESTFul endpoint from the service:
module Application {
export module Services {
export class MyService {
public static $inject = ["$http"];
constructor(private $http: ng.IHttpService) {
}
getSomeData = (model: Models.RequestModel): ng.IPromise<Models.ResponseModel> => {
this.$http.post("url", model).then((response: ng.IHttpPromiseCallbackArg<Models.ResponseModel>) => {
return response.data;
});
}
}
}
}
So basically I am sending the RequestModel and receiving back the ResponseModel
Would that be the proper use/syntax?
So basically I am sending the RequestModel and receiving back the ResponseModel, Would that be the proper use/syntax?
Yes. Request in, promise to Response out.