I retrieve data from a web service in a promise and display it using EJS. The problem is that the HTTP page is not displayed until the promise is fulfilled which makes sense since I call render inside "then".
Is there a way to have the HTTP page displayed without "data" and the "data" displayed when the webService call completes?
var webService = new webService();
webService.GetData("https://somewebservice.com")
.then( (result) =>
{
let options: Object =
{
"data": result
};
this.render(req, res, "index", options);
});
So this might mean you have to restructure your code. But there is something called an observable. It's like a promise, but you subscribe to it which means that after you make the call the callback function is always monitoring it and updating whenever something is returned. It would require a restructure but here is a link to a tutorial.
It would also be good to note that your code will probably need to be restructured anyway, the page will need to load and then make a call for the data if that's the way you want to handle it.
Let me know if this helps.
https://medium.com/#benlesh/learning-observable-by-building-observable-d5da57405d87
The solution I ended up with is:
The page has an onLoad handler on <body> that calls a JSON API on my server using '$.getJSON'
The JSON API calls the web service using promises and in the last 'then' sets 'res.json'
The onLoad handler upon API response updates the HTTP element by setting its text.
This way the page is loaded and displayed then the onLoad handler fires up and deals with the web service and updates the page.
However I would have liked all of this to be transparent, it would have been great if EJS could take care of all of that through a simple assignment.
Related
For example, I want to signal to the client side that a username sent via the POST method in an HTML form already exists in my database.
I know how to recuperate POST data with body-parser and I know how to look it up in a MySQL database.
I know that I could use Ajax to write an error message directly on the form. What does my NodeJS server need to send and how does it send this information?
I've searched through numerous tutorials and I just found solutions where they send a new HTML page. I want to keep my web page the same and use functions like appendChild() to post the error message.
There are a couple of ways you could send data from server-side, so NodeJS, to client-side - which I assume in your case would be some JavaScript file like main.js that handles DOM manimulation.
So, the 1st way you could send data is through a templating engine like Handlebars, for example. There is an easy to use module for express you could get here: hbs.
Now to quickly summarize how an engine like that works, we are basically sending an HTML file like you probably saw in the tutorials, however, a templating engine like Handlebars allows us to send actual data with that file dynamically, so what we would do is render a specific Handlebars template (which in core is just HTML), and pass in a JavaScript object to the render call which would contain all the data you want to pass into that file and then access it in the .hbs file.
So on the server-side, we would write something like this, assuming we have a file called home.hbs and set up Handlebars as the templating engine:
router.get('/home', function(req,res) {
var dataToSendObj = {'title': 'Your Website Title', 'message': 'Hello'};
res.render('home',dataToSendObj);
});
And access in home.hbs like this:
<html>
<header>
{{title}}
</header>
<body>
message from server: {{message}}
</body>
</html>
Now, the issue with this approach is that if you wanted to update the data on the page dynamically, without having to reload the page, using a templating engine would not be ideal. Instead, like you said, you would use AJAX.
So, the 2nd way you could send data from your NodeJS server to the front-end of your website, is using an asynchronous AJAX call.
First, add a route to whatever route handler you are using for AJAX to make a call to. This where you have some logic to perhaps access the database, make some checks and return some useful information back to client.
router.get('/path/for/ajax/call', function(req,res) {
// make some calls to database, fetch some data, information, check state, etc...
var dataToSendToClient = {'message': 'error message from server'};
// convert whatever we want to send (preferably should be an object) to JSON
var JSONdata = JSON.stringify(dataToSendToClient);
res.send(JSONdata);
});
Assuming you have some file such as main.js, create an AJAX request with callbacks to listen to certain event responses like this:
var req = new XMLHttpRequest();
var url = '/path/for/ajax/call';
req.open('GET',url,true); // set this to POST if you would like
req.addEventListener('load',onLoad);
req.addEventListener('error',onError);
req.send();
function onLoad() {
var response = this.responseText;
var parsedResponse = JSON.parse(response);
// access your data newly received data here and update your DOM with appendChild(), findElementById(), etc...
var messageToDisplay = parsedResponse['message'];
// append child (with text value of messageToDisplay for instance) here or do some more stuff
}
function onError() {
// handle error here, print message perhaps
console.log('error receiving async AJAX call');
}
To summarize the above approach using AJAX, this would be the flow of the interaction:
Action is triggered on client-side (like button pressed)
The event handler for that creates a new AJAX request, sets up the callback so it knows what to do when the response comes back from the server, and sends the request
The GET or POST request sent is caught by our route handler on the server
Server side logic is executed to get data from database, state, etc...
The new data is fetched, placed into a JSON object, and sent back by the server
The client AJAX's event listener for either load or error catches the response and executes the callback
In the case of a successful response load, we parse the response, and update the client-side UI
Hope this is helpful!
ReactJS, original Flux, react-router, nodeJS, socket.io
Everything is up to date.
If i'm switching off javascript in browser, only static code is being rendered.
During server side render ComponentWillMount and render methods being fired up, but not ComponentDidMount.
Even if I'm putting Flux logic into ComponentWillMount method, nothing happen: action is called, but socket.io doesn't send request to server to get data from database. Which means, no data being retrieved from database and nothing useful for search engines is being rendered.
If javascript is enabled, everything works perfect.
Here the important pieces of code:
Component. Add listener and call action:
componentDidMount() {
StoreUser.addChangeListener(this._onChange);
Actions.getUser(this.props.params.userid)
}
Client's action asks server for user data:
function _getUser (userid) {
socket.emit('getUser', userid)
}
up until this place server-side rendering works, but server itself doesn't received getUser event, so nothing happens further.
Again, if javascript is enabled in browser, all this works fine. Server receives this call and returns user's data.
How do i make server receive this event, return user's data and render it before sending to client?
As alternative, may be there is different way to make it SEO friendly?
React's componentDidMount lifecycle hook is not called server-side, as stated in the docs.
If you need to fetch data and use it server-side in the render method of a component, you need to pass this data as props during the initial render. This means, you cannot fetch it either during componentWillMount, even if the hook is called.
To achieve what you want, you need your server-side code to:
determine what components will be rendered
dispatch the proper actions so that your store will be properly populated
render your components only then - as the data is available to pass to your components in an initial render
The details on how to achieve that would of course depend on your flux implementation, the framework you use server-side, etc.
I am writing a node/express app that uses the request module get the json data from a url when a route is hit. Also I want to continuously get the data without hitting the reload button from the browser.Is there a way to automatically access the route periodically.
You can have Javascript in the browser that uses setInterval() to repeatedly call a function that makes an Ajax call to your server, fetches new data from your server and then inserts it into the page.
If you just want you page to reload automatically, you can use the meta refresh tag. Example:
<meta http-equiv="refresh" content="3;url=http://www.mozilla.org/">
Or, if your question is really about how to you just regular do some operation in node.js, then you can just use setInterval() within node.js to call some function every xxx ms.
// execute a function every 5 seconds
setInterval(function() {
// do something here
}, 5000);
If you want the code that is execute regularly to be the same code that a route uses, then put that code in a function and call that function from both the interval timer and from your route. To fully automate an actual route call, you'd have to make a request to your own http server that would create the request and response objects for you, but that is probably not what you really need to do.
I'm using https://github.com/LearnBoost/tobi, a browser simulator, to test an external web app. I'd like to be able to see the response body returned in the callback.
I understand the normal way node.js server-side apps show body is via res.on('data'), but my understanding is that inside the toby browser callback the response is now complete. Yet I can't find a res.body, res.data, or anything similar. Nor can I find docs on the topic!
function(error, response, $){
// Headers are there
console.log(response.headers;
// Horrible hack to show body via jquery as response.body and response.data are undefined
console.log($('body').html());
}
Per the above, I can see the document data via jQuery, so it's there. I just can't find it inside response...
I think your jQuery usage is the intended way to use tobi. It consumes the response and gives you a $ to manipulate or examine it.
I know that you can add a listener to the chrome.tabs.onUpdated event so that you can run code when a new tab is opened or the url of a tab changes.
However I was wondering is there a similar event/hook you can listen to so that you can run code when an AJAX call returns?
I'm asking because I need to check a web page every 3 seconds to see if certain text has appeared through AJAX. So basically I have to poll the page. Obviously it would be more efficient if I didn't have to poll the page and if I could run the code only when AJAX calls return as that is when I need to do the scan.
So is there a hook/even for this or will I just have to stick to polling the page?
There is the experimental webRequest API, that allows you to hook into all HTTP requests made by the browser. Since it's experimental you'd have to enable the --enable-experimental-extension-apis flag in chrome://flags or on the command line
That callback would be executed by the same javascript that called that ajax event. Its usually referred to as an ajax callback method.
In jQuery its:
$.ajax({method: "GET", url: 'some url' }).complete(function() { //do your function here });
in Mootools its:
new Request.JSON({ method: "GET", url: 'someurl', onComplete: function() { //do your function here });
In plain old javascript, you have to write in functionality for a custom callback into your XmlHttpRequest function as a function that executes when a certain ajax status code is reached