Hi i am working on my Angular 7 project. I am getting one response from a api and i want to integrate that response to other api which result success in all other apis.
Here is my code :
ngOnInit() {
this.second()
}
first() {
this.service.getId(id).resp.subscribe((res => {
console.log(res);
this.firstresp = res;
});
}
second() {
this.service.getId(this.firstresp).resp.subscribe((res => {
console.log(res)
});
}
Here the problem is first function executed properly and second function i am getting response only after refreshing the page. Any solution? TIA.
This is actually an RXJS question, not an angular one. You want to use switchMap:
this.service.getId(id).resp.pipe(
switchMap((res) => {
return this.service.getId(res).resp;
})
).subscribe((rep) => {
....
});
switchMap above pipes the result of the first call into the second one then emits that result to the subscribe. No need for the firstresp etc.
Related
I wanted to get the result which maches the query. I've tested the api so basically the api has no problem , the problem is with my angular code.
I wanted to return the data the maches the "where" query , and then I use subcribe but it returns empty , any idea? . Thank you.
Angular service
checkExistingFeedbackRequest(formGroup: FormGroup): Observable<FeedbackRequest[]> {
return from(this.service.find<FeedbackRequest>({
where: {
formId: formGroup.Id,
respondentId: formGroup.respondentId,
recipientId:formGroup.recipientId,
periodStartDate: formGroup.periodStartDate,
periodEndDate: formGroup.periodEndDate),
},
}))
.pipe(
map((result) => result.data)
);
}
component.ts
let test = this.requestFormService.checkExistingFeedbackRequest(this.form)
.subscribe((result) => {
console.log("result", result)
})
I would like to launch a new request if this function in relation with my services works, how to proceed? Thank you
test.component.ts
destroyUnicorn(item){
this.itemService.updateUnicorn( {
statut: "destroyed",
id: item.id
});
}
item.service.ts
updateUnicorn(item) {
this.itemDoc = this.afs.doc("unicorns/${item.id}");
this.itemDoc.update(item) <------ FireStore request
.then(function() {})
.catch(function() {});
}
Global idea :
-- 1 ° In my template, I click on a button who execute the function deleteUnicorn of my component.
--- 2 ° The deleteUnicorn function sends the parameters to the updateUnicorn function in my services, which sends a request to Firestore to modify the content in the database.
-- 3 ° I would like, when the function is finished and works, to be able to execute a new function which will modify the user's money in another table of the database.
You can chain promises. Change updateUnicorn() method in order to return a resolved promise and then add your desired functionality:
destroyUnicorn(item){
this.itemService.updateUnicorn( {
statut: "destroyed",
id: item.id
})
.then(function(something) {
// This will execute if updateUnicorn resolves.
});
}
And in your updateUnicorn method:
updateUnicorn(item) {
this.itemDoc = this.afs.doc("unicorns/${item.id}");
this.itemDoc.update(item) <------ FireStore request
.then(function(something) {
return Promise.resolve(something);
})
.catch(function() {});
}
Also, if you don't need to use the response of the itemDoc.update() method, you could simply update the function like this:
updateUnicorn(item) {
this.itemDoc = this.afs.doc("unicorns/${item.id}");
return this.itemDoc.update(item);
}
And the destroyUnicorn() will remain the same.
I am trying to use the Fetch API with my Rails application. I can pass parameters to the controller as part of a query string, but still can't figure out how to pass JSON data or where to find it in the controller. A sample call looks like the below. Where can I access my test data on in the controller? Happy Sunday :)
export const fetchControllerData = () => {
return fetch('api/users',), {
body: { "test": "test" }
})
.then(res => res.json());
};
I'm in the process of working out my own issues with fetch and Rails. But I'll take a stab at this.
I expect that fetch is using GET as the default method - which won't use the body at all. You will likely need to set the method to be POST to get the body through. Further to that you might need to set the Content-Type header (to application/json) in order to send the data through as JSON.
May be u need to send params in this way for get request and use this link for https://github.com/axios/axios
export const fetchControllerData = () => {
params = { body: { "test": "test" } }
return HTTP.get('api/users', params)
.then((response) => {
if (response.success) {
// do something here
} else {
// handle error condtion here
}
});
}
I am trying to use the Firebase API in my Angular 2 application.
Here is what I have in my Service:
fbGetData() {
firebase.database().ref('/path/to/data').on('value',(snapshot) => {
this.data = snapshot.val();
console.log(this.data); //This logs my data
return this.data;
})
}
This is what I have in my Component:
ngOnInit() {
this.data = this.dataService.fbGetData();
console.log(this.data); //This logs undefined
}
The component logs undefined and then the service logs the array of objects. Thanks in advance for any help.
As #jonrsharpe commented: Firebase retrieves data from its servers asynchronous. Your browser won't wait for this result, as that would block the user from doing other actions. So you cannot return the data from fbGetData as it hasn't been loaded yet.
There are two ways to work with asynchronous loading:
use a callback
return a promise
use a callback
The trick for asynchronous loading is to reframe your solution from "first get the data, then print it" to "whenever the data is loaded, print it".
In code this translates to:
fbGetData() {
firebase.database().ref('/path/to/data').on('value',(snapshot) => {
this.data = snapshot.val();
console.log(this.data);
})
}
fbGetData();
So the logging is now purely in on() callback.
Of course you might want to do something different with the data at different times, so you can pass in a callback to fbGetData():
fbGetData(callback) {
firebase.database().ref('/path/to/data').on('value',(snapshot) => {
this.data = snapshot.val();
callback(this.data);
})
}
fbGetData(data => console.log(data));
Of course at this stage, you should consider if you shouldn't simply be invoking your own callback with a snapshot:
fbGetData(callback) {
firebase.database().ref('/path/to/data').on('value',callback);
}
fbGetData(data => console.log(data.val()));
return a promise
In the above example the data will be printed when it is initially loaded from the server and whenever the data on the server is changed. This is part of the magic of the Firebase Database: it synchronizes both the current value and any changes to that value.
If you only care about the current value, you can also use once(). This method can take a callback, but it can alternatively also return a promise. That means that you have something that you can return from fbGetData:
fbGetData() {
var promise = firebase.database().ref('/path/to/data').once('value');
return promise;
}
fbGetData().then(snapshot => console.log(snapshot.cal());
With this snippet the value will only be printed (at most) once, since you're using once().
You can try the subscribe method to get data. The Observable can be subscribed ,mapped and can be converted into JSON.
Have a look at the code and see if you can get something.
public sessions(): any {
return this.http.get('api/ResultsAPI') //.get('api/vehicles.json')
.map(
(response: Response) => <any>response.json())
.do
(
response => response
);
}
To call the service use this
this.ApiService.sessions().subscribe(
data => {
this.api = data;
this.getdata(this.api);
}
);
I'm guessing this should be somewhat easy to achieve but I've having trouble (conceptually, I guess) figuring out how to tackle it.
What I have is an API that returns an array of JSON objects. I need to step through these objects, and, for each object, make another AJAX call. The issue is the system that handles each AJAX call can only handle two active calls at a time (as it's quite a CPU-intensive task that hooks out into a desktop application).
I was wondering how I could achieve this using RxJS (either using version 5 or 4)?
EDIT: In addition, is it possible to have a chain of steps running concurrently. i.e.
Downloading File: 1
Processing File: 1
Converting File: 1
Uploading File: 1
Downloading File: 2
Processing File: 2
Converting File: 2
Uploading File: 2
Downloading File: 3
Processing File: 3
Converting File: 3
Uploading File: 3
I've tried doing something like:
Rx.Observable.fromPromise(start())
.concatMap(arr => Rx.Observable.from(arr))
.concatMap(x => downloadFile(x))
.concatMap((entry) => processFile(entry))
.concatMap((entry) => convertFile(entry))
.concatMap((entry) => UploadFile(entry))
.subscribe(
data => console.log('data', new Date().getTime(), data),
error => logger.warn('err', error),
complete => logger.info('complete')
);
However that doesn't seem to work. The downloadFile, for example doesn't wait for processFile, convertFile and uploadFile to all complete, rather, the next one will run again as soon as the previous one completes.
Here are 2 approaches, if you want the sequence of requests exactly like this
Downloading File: 1
Processing File: 1
Converting File: 1
Uploading File: 1
Downloading File: 2
Processing File: 2
...
You need to resolve all promises inside single concatMap method, like this
Rx.Observable.fromPromise(getJSONOfAjaxRequests())
.flatMap(function(x) { return x;})
.concatMap(function(item) {
return downloadFile(item)
.then(processFile)
.then(convertFile);
})
.subscribe(function(data) {
console.log(data);
});
see the working plunkr here: https://plnkr.co/edit/iugdlC2PpW3NeNF2yLzS?p=preview
This way, the new ajax call will be sent only when the previous is finished.
Another approach is that allow the files to send requests in parallel but the operations 'downloading,processing,converting,uploading' will be in sequence. For this you can get it working by
Rx.Observable.fromPromise(getJSONOfAjaxRequests())
.flatMap(function(x) { return x;})
.merge(2) // in case maximum concurrency required is 2
.concatMap(function(item) {
return downloadFile(item);
})
.concatMap(function(item) {
return processFile(item);
})
.concatMap(function(item) {
return convertFile(item)
})
.subscribe(function(data) {
//console.log(data);
});
see plunkr here: https://plnkr.co/edit/mkDj6Q7lt72jZKQk8r0p?p=preview
You could use merge operator with the maxConcurrency overload (Rxjs v4), so something like :
Rx.Observable.fromArray(aJSONs)
.map (function (JSONObject) {
return ajaxRequest(JSONObject) // that would be an observable (or a promise)
})
.merge(2)
You can have a look to see other examples of use at :
Limit number of requests at a time with RxJS,
or How to limit the concurrency of flatMap?
Official documentation :
merge(maxConcurrency)
How about something like this? You could use from to break the array into bite sized chunks and process them one by one using concatMap.
function getArr() {
return Rx.Observable.of([1, 2, 3, 4, 5, 6, 7, 8]);
}
function processElement(element) {
return Rx.Observable.of(element)
.delay(500);
}
getArr()
.concatMap(arr => {
return Rx.Observable.from(arr);
})
.concatMap(element => {
return processElement(element);
})
.subscribe(res => {
console.log(res);
});
Old post but I believe this could work, for console log we could use tap. Note editor would through intellisense error since from expects an array, but the code should work.
from(start()).pipe(
switchMap(files => from(files).pipe(
switchMap(file => from(downloadFile(file)).pipe(
map(_ => ({file: file, downloaded: true}))
)),
switchMap(attr => from(processFile(attr.file)).pipe(
map(_ => ({...attr, downloaded: true}))
)),
switchMap(attr => from(convertFile(attr.file)).pipe(
map(_ => ({...attr, converted: true}))
)),
switchMap(attr => from(uploadFile(attr.file)).pipe(
map(_ => ({...attr, uploaded: true}))
))
))
).subscribe(_ => {})