Angular 2 Rxjs creating action after server response - javascript

I am a new in Angular2(and especially to RxJs library) and stacked on next step. My web site starts with a register page.
And after the completion of of register form i have base service.auth.ts method register usage
registerUser(){
this.authService.registerUser(this.registrationForm.value)
.subscribe((data) => {
console.log(data);
})
//this line should apear after server response from backend
console.log('AFTER SERVER RESPONSE')
}
And i recieve response like this
I read some stuff about flatMap method in RxJs documentation and it is claimed to be alternative to default Promise method then() - but i failed to create working instance of code that acutally implements flatMap method for my case
So the question is : How can i achieve result so 'AFTER SERVER RESPONSE' message appears AFTER server response? (not before as mentioned on previous screenshot)

You should wait for asynchronous task to complete. Move that console.log('AFTER SERVER RESPONSE') inside your subscribe block.
registerUser() {
this.authService.registerUser(this.registrationForm.value)
.subscribe((data) => {
console.log(data);
//this line should apear after server response from backend
console.log('AFTER SERVER RESPONSE')
});
// anything written over here will execute before `registerUser()` returns data
console.log('THIS WILL PRINT BEFORE SERVER RESPONSE')
}

Related

Is there a way to send acknowledgement response in AWS Lambda functions

I am trying to handle a modal submission in slack, but there are some database operations in between which are taking a few seconds of time, due to this delay, I am getting: We had some trouble connecting error when submitting slack dialog (Slack API)
I know in node.js we can do something like this:
app.post('/', async (req, res){
res.status(200).send({text: 'Acknowledgement received !'});
// handle other task
return res.json({done: 'Yipee !'})
})
But in AWS Lambda function, I have no idea how will I handle this acknowledgement response in 3 sec.
module.exports.events = async (event, context, callback) => {
??? -> How to handle acknowledgement here, it must be handled at top.
// handle task
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({text: 'Done !'})
}
}
If all you want to do is to get notified for a successfull invocation and then have the lambda keep doing its own thing you can invoke lambda asynchronously by setting the InvocationType parameter to Event. https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax
Slack's API can be difficult to handle with a serverless architecture, as most serverless implementations like the response to be the last thing they do, rather than the first. One approach would be to wrap any required behaviour inside a promise, and only resolve that promise once you have handled the task. See here for an example of this.

Javascript Fetch API equivalent in Java for Http requests?

I am currently learning about Threads in Java. I wanted to know what the standard protocol would be when making Http Requests in Java that would be similar to the code I have below, which uses Javascript Fetch API and asynchronous programming. For example, if I was using the Fetch API in Javascript to first make a GET request to grab some data from a REST endpoint that I would later use to make a POST request (as seen in the code below), I would need to use a Callback function or Promise (like below) to wait until that first request has retrieved its data for the second request to then proceed. Obviously, if I did not use Promises or nest the second Http POST in the first Fetch method (GET) below, and wrote two separate Fetch API calls (one for GET, one for POST, sequentially one after other aka top-to-bottom), both calls would "fire-off" simultaneously and the second POST request wouldn't have the data it needs to make a successful POST.
const myHttpGETandPOSTmethod = () => {
// First Http request goes here
fetch('http://example.com/movies.json', {
method: 'GET',
headers: // Some headers here,
})
.then(response => response.json())
.then(data => {
console.log(data))
// Nest the second Http request inside here. It only runs after 1st request completes
return fetch('http://example.com/movies.json', {
method: 'POST',
headers: // Some headers here,
body: JSON.stringify(body);
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
})
}
So then, if I were using something like the Apache HttpClient https://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html library in Java, would the standard procedure be to "spin-up" another Thread (besides the main thread) to execute the GET request and then do a thread.join() such that after the first thread completes, then the second request can fire-off its own Thread?
Would I need to use a Callable instead of Runnable so that I can save the HttpEntity data response of the first GET request?
I guess I'm just trying to understand the best way to implement the scenario I posed above regarding an HTTP GET request that is needed to make a subsequent POST request, while both fires asynchronously such that they do not block the main thread.
You can make a basic GET request using the apache Http Library as such (POST is also very similar):
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://targethost/homepage");
CloseableHttpResponse response1 = httpclient.execute(httpGet);
try {
System.out.println(response1.getStatusLine());
HttpEntity entity1 = response1.getEntity();
// Save the response body to a string
String body = EntityUtils.toString(entity1, StandardCharsets.UTF_8);
System.out.println(body);
EntityUtils.consume(entity1);
} finally {
response1.close();
}
Or am I on the wrong approach here and looking at this incorrectly? I believe the Http library in Apache offers both synchronous and asynchronous Http calls? or should I be using a newer library for Http in Java?

Overwriting an existing command with Cypress

I'm trying to overwrite an existing command in Cypress.io. I'm looking to log() a route response's status & the route's url to extend the functionality of the built-in route(). Unfortunately, I get this message The route undefined had a undefined status code. in the console. Note, I'm using the browser's console momentarily. Eventually, I'll use the log() built-in method. This is what I have tried so far:
cypress/support/commands.js
Cypress.Commands.overwrite('route', (originalFn, response) => {
console.log(`The route ${response.url} had a ${response.status} status code.`);
return originalFn(response);
});
Update:
I'm getting the route now, but I still don't get response or status. This is my current code:
Cypress.Commands.overwrite('route', (originalFn, url, response) => {
console.log(`The route ${url} had ${response} status code`);
return originalFn(url, response);
});
When using the pattern cy.route(method, url, response), the response parameter is use to stub the call and return the supplied response to your app, see (route() - Arguments)
response (String, Object, Array)
Supply a response body to stub in the matching route.
Note that creating an overwrite of cy.route() will be hooking into the route configuration, not the capture of the route.
The pattern cy.route(options) has an onResponse option which can be used to console.log() the response, but cy.log() does not work there, probably because we invoke a command inside a command.
Cypress.log() can be used instead.
cy.route({
url: 'http://example.com',
method: 'GET',
onResponse: (response => {
const message = `The route '${response.url}' had a ${response.status} status code.`;
const log = Cypress.log({
displayName: 'Route debugging',
message: message,
consoleProps: () => {
// return an object which will
// print to dev tools console on click
return {
message: message,
}
}
})
log.finish(); // remove log spinner
})
})
/*
Command log output:
ROUTE DEBUGGING
The route 'http://example.com' had a 200 status code.
*/
Depending on what you're trying to achieve, there are a couple of options. Richard's answer above describes one approach - I'll attempt to cover some others.
(Note: The Cypress documentation at https://docs.cypress.io/ probably will give you a better understanding than this answer. I'll try to link the relevant articles inline)
(You can skip ahead to the section on 'Inspecting Api Responses' if you don't care why your code isn't working)
What's happening in your code
Let's look at the example code from https://docs.cypress.io/api/commands/route.html#Examples
cy.server()
cy.route('**/users').as('getUsers')
cy.visit('/users')
cy.wait('#getUsers')
Without your overwrite, cy.route here just registers the route, so you can wait for it later (Remember, cy.route does not make any api calls itself). With your overwrite, cy.route is completely replaced with your callback:
Cypress.Commands.overwrite('route', (originalFn, url, response) => {
console.log(`The route ${url} had ${response} status code`);
return originalFn(url, response);
});
So when cy.route('**/users') is called, it will instead evaluate
(originalFn, url, response) => {
console.log(`The route ${url} had ${response} status code`); // Logs "The route **/users had undefined status code"
return originalFn(url, response); // Registers the route with an mock value of undefined
})(originalCypressRouteFn, '**/users')
You can see why response is undefined - it's not passed in to the route call at all, since the request hasn't even been made.
Note that if we were attempting to mock the call instead (See https://docs.cypress.io/api/commands/route.html#With-Stubbing)
cy.route('https://localhost:7777/surveys/customer?email=john#doe.com', [
{
id: 1,
name: 'john'
}
])
You would instead log
"The route https://localhost:7777/surveys/customer?email=john#doe.com had [object Object] status code"
Inspecting Api Responses
If you just want to inspect the response from an api, you can use the using the built-in debugging tools (after calling cypress open). The browser's Network tab is available (which will record all requests made during a given test run), and you can additionally click on the response recorded in the left panel, which will log the request and response to the browser console.
If you're attempting to assert on the response to an api call, you can use cy.wait (See https://docs.cypress.io/guides/guides/network-requests.html#Waiting) to get access to the underlying xhr request after it finishes:
cy.wait('#apiCheck').then((xhr) => {
assert.isNotNull(xhr.response.body.data, '1st API call has data')
})
If you want a record of the APIs calls made during a CLI run (using cypress run), you can:
Print debug info, which will give you a lot of information, including all requests and responses (See https://docs.cypress.io/guides/references/troubleshooting.html#Print-DEBUG-logs): DEBUG=cypress:* cypress run (You can change cypress:* to limit the scope of the debug to just api calls, though I don't know off the top of my head what the namespace you'll want is)
Use a plugin that records all requests (e.g. https://github.com/NeuraLegion/cypress-har-generator)

Send response and continue to perform tasks Express | Node.js

In Node.js (which I'm new to) I am trying to perform a series of tasks after receiving a response. However, I want to make the response time as fast as possible. I don't need to return the results of these tasks to the client, so I'm trying to return the response immediately.
My current implementation is roughly:
var requestTime = Date.now;
app.post('/messages', function (req, res) {
console.log("received request");
// handle the response
var body = res.body;
res.send('Success');
res.end();
console.log("sent response");
performComplexTasks(body)
})
function performComplexTasks(body){
// perform data with body data here;
console.log("finished tasks:", Date.now()-requestTime, "ms");
}
// -------LOG-----------
// received request
// POST /api/messages 200 3.685 ms - 59
// sent response
// finished tasks: 2500ms
The client making the request seems to hang until performComplexTasks() is finished. (The POST finishes in 3.685ms, but the response takes 2500ms to finish.)
Is there a way to send the response immediately and complete other tasks without having the client wait/hang? (In my case, the client cannot make multiple API calls.)
If your job is not super-CPU-intense and you can tolerate some work on the main server thread, then just use await to break the execution so that the request can be properly sent. You can use setTimeout or await.
// This line is wrong too - ask a separate question if needed
var requestTime = Date.now;
app.post('/messages', async function (req, res) {
console.log("received request");
// handle the response
var body = res.body;
res.status(200).send({ success: true });
console.log("sent response");
// Method 1:
await performComplexTasks(body)
// Method 2:
setTimeout(() => performComplexTasks(body), 0);
})
async function performComplexTasks(body){
// The line below is required if using the `await` method -
// it breaks execution and allows your previous function to
// continue, otherwise we will only resume the other function after
// this function is completed.
await new Promise(resolve => setTimeout(resolve, 1));
// perform data with body data here;
console.log("finished tasks:", Date.now()-requestTime, "ms");
}
This isn't really a fantastic solution and you'd need to use worker threads for long operations.
Am I right that you're trying to execute a CPU-intensive job in performComplexTasks? If so, then event loop is being locked by that task and new requests are waiting until the job is finished.
It's a bad practice in node.js to execute such 'complex' tasks in the same process as http server. Consider using background workers, queues or something like that.
See this topic for details: Node.js and CPU intensive requests

node.js and hapi: fetching data from a database synchronously

Coming from a .net world where synchronicity is a given I can query my data from a back end source such as a database, lucene, or even another API, I'm having a trouble finding a good sample of this for node.js where async is the norm.
The issue I'm having is that a client is making an API call to my hapi server, and from there I need to take in the parameters and form an Elasticsearch query to call, using the request library, and then wait for the instance to return before populating my view and sending it back to the client, problem being is that the request library uses a callback once the data is returned, and the empty view has long been returned to the client by then.
Attempting to place the return within the call back doesn't work since the EOF for the javascript was already hit and null returned in it's place, what is the best way to retrieve data within a service call?
EX:
var request = require('request');
var options = {
url: 'localhost:9200',
path: {params},
body: {
{params}
}
}
request.get(options, function(error, response){
// do data manipulation and set view data
}
// generate the view and return the view to be sent back to client
Wrap request call in your hapi handler by nesting callbacks so that the async tasks execute in the correct logic order. Pseudo hapi handler code is as following
function (request, reply) {
Elasticsearch.query((err, results) => {
if (err) {
return reply('Error occurred getting info from Elasticsearch')
}
//data is available for view
});
}
As I said earlier in your last question, use hapi's pre handlers to help you do async tasks before replying to your client. See docs here for more info. Also use wreck instead of request it is more robust and simpler to use

Categories