Unable to make a sequential service (HTTP) calls in Angular 5 by using Joins - angular5

I had a Array with N number of objects. I want to make a service call sequentially. One response comes based on that i will make a another request. Please provide a better approach to handle this scenario through JOINS in Angular 5.

You can use switchMap for this.
nestedCalls(user: any) {
return this.http.get('YOUR_URL').pipe(
switchMap(data => {
const body = {
// do your work woth data - first service object
};
return this.http.post('YOUR_URL', body);
})
)
}
Or you can do something like below also :
this.service.getData(id, (response) => {
this.service.getInitiatedEntity(response.id).subscribe(
(retData) => {
// response - 1st service data
// retData - 2nd service data
}
);
});
Hope this help.

Related

How to unregister middleware in Telegraf?

When I add bot.hears(...), it registers middleware for handling matching text messages. But now it will handle those messages even if they are sent any time, even if not expected.
So if I am creating a stateful service, I would like to listen to particular messages only at appropriate time.
How can I unregister middleware, so that it does not hear any more previously handled messages?
I turned out I was looking for Scenes. How to use them is described on Github.
I'll just post a slightly modified code from the links above:
const { Telegraf, Scenes, session } = require('telegraf')
const contactDataWizard = new Scenes.WizardScene(
'CONTACT_DATA_WIZARD_SCENE_ID', // first argument is Scene_ID, same as for BaseScene
(ctx) => {
ctx.reply('Please enter guest\'s first name', Markup.removeKeyboard());
ctx.wizard.state.contactData = {};
return ctx.wizard.next();
},
(ctx) => {
// validation example
if (ctx.message.text.length < 2) {
ctx.reply('Please enter real name');
return;
}
ctx.wizard.state.contactData.firstName = ctx.message.text;
ctx.reply('And last name...');
return ctx.wizard.next();
},
);
const stage = new Scenes.Stage();
stage.register(contactDataWizard);
bot.use(session());
bot.use(stage.middleware());
But I still don't know how to generally implement it, so I need to find it out in the Scenes code of Telegraf.

Need my server to return a response that includes a data error. Need client to see what was wrong with data in request

As it will become quickly apparent, I have never seriously written a webserver before
Here is the current scenario:
Clients make requests to webserver, asking to save some data
Server looks at payload, and makes 2 checks
a. Is this client banned from saving data?
b. Does the payload of this data pass a language filter?
Server responds with success, or one of those 2 errors
My endpoint is written with Express in TypeScript
class ChatRequest {
public uid: string;
public message: string;
}
export const register = (app: express.Application, deps: dependencies.IDependencies) => {
app.post("/sendChat", (req: express.Request, res: express.Response) => {
transformAndValidate(ChatRequest, req.body)
.then((sendGlobalChatRequest: SendGlobalChatRequest) => {
const payload = {
message: sendGlobalChatRequest.message,
uid: sendGlobalChatRequest.uid
};
//Check if uid is banned here
//Check if payload passes language filter here
//Save Payload here
res.sendStatus(200);
}, (err) => {
deps.logger.error(err);
res.sendStatus(503);
});
});
I have been using this article for reference:
https://hackernoon.com/the-request-sent-bad-data-whats-the-response-94088bd290a
But I think my conclusion is that they are discussing something slightly different.
So from my understanding, I can just make up HTTP codes...
so I could just do res.sendStatus(499); if the uid is banned, and maybe res.sendStatus(498); if the payload doesn't pass language filter
Then my client can just read the Int statusCode and quickly determine the failure.
But even though I think I can do that, and it would work, it doesn't seem right?
Should I instead be using a standard HTTP Response Code? https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
And then add in the body of the response, a String or something that my client can parse to determine the error?
The String parsing seems way harder to maintain, but technically seems more "legal" if that makes sense?
What is the best way for me to have a client determine the type of server-side error?
I decided to return 400 with a JSON mapping errors to bools
if (isProfane(message)) {
res.status(400).json({messageContentBlocked: true});
}
In this way the client can receive multiple errors for the request at once, and it's more explicit
And in case anyone is googling around, I am using RxSwift/RxCocoa
Here is how I handle the error on the client:
extension Error {
var chatMessageBlockedURLError: Bool {
guard let rxCocoaURLError = self as? RxCocoaURLError else {return false}
switch rxCocoaURLError {
case let .httpRequestFailed(response, data):
guard response.statusCode == 400, let data = data else {return false}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .millisecondsSince1970
guard let errors = try? decoder.decode([String:Bool].self, from: data) else {return false}
return errors["messageContentBlocked"] == true
default:
return false
}
}
}

Angular multiple rest api request

im new on Angular and have a question.
I need to call 2 API Rest, on second API i need result of first API.
I have this code:
ngOnInit() {
this.Jarwis.getmyinfo()
.subscribe(
// data => console.log(data),
data => this.Getmyinfo = data,
error => console.log(error),
);
this.Jarwis.showazienda(id_azienda).subscribe(
// data => console.log(data),
data => this.Showazienda = data,
error => console.log(error),
);
}
This is a call to API rest in Jarwis:
getmyinfo(): Observable {
return this.http.get(${this.baseUrl}/me);
}
showazienda(data): Observable {
return this.http.get(${this.baseUrl}/showazienda/ + data);
}
getmyinfo is first HTTP REQUEST and where i need to get id_azienda for second HTTP REQUEST (showazienda)
I think need map result of first http request in json and get result of id_azienda but im not able to do it.
If i set 1 in the parameters of showazienda im able to get and show info of API.
For observables, you use the ".flatMap" to chain multiple async actions together (this is very similar to the promises ".then"). The flatMap allows you to used to chain multiple async requests together and have them execute one by one in order.
Here is a good explanation of flatMap.
So for your example, you would do something like this:
ngOnInit() {
this.Jarwis.getmyinfo()
.flatMap(
(data) => {
this.Getmyinfo = data;
// get id_azienda from data
return this.Jarwis.showazienda(id_azienda);
}
).subscribe(
// data => console.log(data),
data => this.Showazienda = data,
error => console.log(error),
);
}
This example code will first send the "getmyinfo()" request. Once the response is received the ".flatMap" will be called with the data received from "getmyinfo()". You can then used this data to get the "id_azienda". Then you can make the second request to "showazienda". The observable returned from "showazienda()" needs to be returned in the flatMap. Then you subscribe to the modified observable and the data you receive will be the result from the "showazienda()" request.

Variable Doesn't Change in Vue.js

I can't change the variable qty in my computed properties.
getQuantity(){
return (qtyId) => {
var qty = 0;
axios.get( window.location.origin + '/api/quantity/' + qtyId)
.then(res => {
console.log(res.data.qty)
qty = res.data.qty
})
.catch()
console.log(qty)
return qty
}
},
It is an asynchronous request using axios. the console.log(res.data.qty) works fine it output 4 but the console.log(qty) is 0. I think it's because of asynchronous request... How can I make it work... TY
I think it's because of asynchronous request
It definitely is.
If you're not familiar with writing asynchronous code, I would read up on that first (in particular promises).
console.log(qty) returns 0 because that code is executed immediately after the request is sent and before the response has come back from the server. The callback function you passed to then is the function that will be executed once the response has come back from the server, and only then will you be able to obtain qty from the response data.
If you want to return qty from that function (which is what it looks like you are trying to do), then that function must return a promise that once resolved will contain the qty value (code isn't blocked in JavaScript, hence the reason for the promise).
getQuantity() {
return (qtyId) => {
return axios.get(window.location.origin + '/api/quantity/' + qtyId)
.then(res => {
return res.data.qty;
});
}
},
Why is it a computed property instead of a method? I think a different approach would be better, but I don't know exactly how this code fits into your project.

Restangular setBaseUrl in the run messed up?

I have three service in my angular service module, and I put
Restangular.setBaseUrl(api_url);
in each of my service with different api_url, and I expect to use different service with different url;
but when I post to one of the service say api_url = a/v1/c/, what I get is post to api_url = b/v1/c;
I think the problem is the setBaseUrl part, for example:
factory.Aservice = function(Restangular){
Restangular.setBaseUrl('/a/v1');
var alist= Restangular.all('c/');
return {
createA:function(){
alist.post(data)
}
}
}
factory.Bservice = function(Restangular){
Restangular.setBaseUrl('/b/v1');
var blist= Restangular.all('d/');
return {
createB:function(){
blist.post(data)
}
}
}
when I call Aservice.createA(),the post url is '/b/v1/c',which is wrong.
any idea why?
You don't seem to understand scoping of a serivce. Angular instantiates services in a lazily-loaded manner. Since both your services operate on the same Restangular, it is normal that whichever service loaded last, would be the one that will override the restangular configuration last:
http://plnkr.co/edit/o974TqeunG9DGQONRNDT?p=preview
I created a Plunkr which illustrates that.
Also created a Plunkr which shows the correct way to do that.
http://plnkr.co/edit/XYEQpLZaRAjxNUImCJMP?p=preview
You can also use separate configurations for each service as explained here: https://github.com/mgonto/restangular#how-to-create-a-restangular-service-with-a-different-configuration-from-the-global-one
app.factory('ServiceA', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
// service has different address from serviceB
RestangularConfigurer.setBaseUrl('http://service-a.example.com/a/v1');
});
});
app.factory('ServiceB', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
// service has different address from serviceA
RestangularConfigurer.setBaseUrl('http://service-b.example.com/b/v1');
});
});