How can I call a restapi function from frontend (ejs/html) [duplicate] - javascript

This question already has answers here:
What is the difference between client-side and server-side programming?
(3 answers)
Closed 3 years ago.
I am trying to basically call the 'get' method from html/ejs when a button is pressed to query the database and display the results. Sorry if it's very simple, but I just can't get it work.
I tried to require the file and call the function inside a script tag but that doesn't work on the browser. I tried to add the js file with a <script src="text/javascript" src="filename"> but that also results in errors.
The rest API I built talks to oracle 11g (Toad) using oracledb.
I am basically trying to call the get function in this class
const employees = require('../db_apis/employees.js');
async function get(req, res, next) {
try {
const context = {};
context.id = parseInt(req.params.id, 10);
const rows = await employees.find(context);
if (req.params.id) {
if (rows.length === 1) {
res.status(200).json(rows[0]);
} else {
res.status(404).end();
}
} else {
res.status(200).json(rows);
}
} catch (err) {
next(err);
}
}
...
db_apis/employees.js
const oracledb = require('oracledb');
const database = require('../services/database');
async function find(context) {
const baseQuery =
`SELECT *
FROM choice_names`;
console.log('in find');
let query = baseQuery;
const binds = {};
let additionalQuery = '\nwhere ';
if (context.id) {
binds.choice_name = context.id;
additionalQuery += `choice_name = :choice_name`;
// query += `\nwhere choice_name = :choice_name`;
} else if (context.user) {
binds.choice_user = context.user;
additionalQuery += `choice_user = :choice_user`;
} else if (context.date) {
binds.choice_date = context.date;
additionalQuery += `choice_date = :choice_date`;
}
if (context.id || context.user || context.date) {
query += additionalQuery;
}
console.log(query);
const result = await database.simpleExecute(query, binds);
return result.rows;
}
...
router.js
const express = require('express');
const router = new express.Router();
const employees = require('../controllers/employees');
router.route('/employees/:id?')
.get(employees.get)
.post(employees.post)
.put(employees.put)
.delete(employees.delete);
module.exports = router;
index.ejs
...
<button onclick="get()">Click me</button>
...

You are (very)confusing frontend and backend code.
The express app is in backend, running on some port, exposing the /employees/:id route.
But the frontend part doesn't have access to the backend scripts, So you need to do a XHR(Ajax) request from frontend to that route and get the result.
For example, in jQuery it can be something as
function get(){
$.get('/employees/1').done(..do something..)
}
You can refer this answer on how to do it on angular.

Related

Javascript working in Chrome, working in firefox locally, but not after deployment

This is part of a Spark Java app, but the error is happening in this JS part. The relevant code is as follows:
const addErrBox = async () => {
const controls = document.querySelector(".pure-controls");
const errBox = document.createElement("p");
errBox.setAttribute("id", "errBox");
errBox.setAttribute("style", "color:red");
errBox.innerHTML = "Short URL not valid or already in use!";
controls.appendChild(errBox);
}
const submitForm = () => {
const form = document.forms.namedItem("new-url-form");
const longUrl = form.elements["longUrl"];
const shortUrl = form.elements["shortUrl"];
const url = `/api/new`;
fetch(url, {
method: "POST",
body: `${longUrl.value};${shortUrl.value}`
})
.then((res) => {
if (!res.ok) {
if (document.getElementById("errBox") == null) {
addErrBox();
}
}
else {
document.getElementById("errBox")?.remove();
longUrl.value = "";
shortUrl.value = "";
refreshData();
}
});
};
(async () => {
await refreshData();
const form = document.forms.namedItem("new-url-form");
form.onsubmit = e => {
e.preventDefault();
submitForm();
}
})();
Basically, "/api/new" checks for validity of input, adds the data to database if valid and prints error otherwise. Now, when the input is valid, it seems to work. The "/api/new" code is in Java, which seems to work properly as well since I do get a 400 error. All of it works properly when built inside a docker locally, but when accessed over internet using Nginx reverse proxy, it stops working inside firefox. Chrome still works. I'm not sure what's happening.
The code for "/api/new" is this:
public static String addUrl(Request req, Response res) {
var body = req.body();
if (body.endsWith(";")) {
body = body + "$";
}
var split = body.split(";");
String longUrl = split[0];
if (split[1].equals("$")) {
split[1] = Utils.randomString();
}
String shortUrl = split[1];
shortUrl = shortUrl.toLowerCase();
var shortUrlPresent = urlRepository
.findForShortUrl(shortUrl);
if (shortUrlPresent.isEmpty() && Utils.validate(shortUrl)) {
return urlRepository.addUrl(longUrl, shortUrl);
} else {
res.status(HttpStatus.BAD_REQUEST_400);
return "shortUrl not valid or already in use";
}
}
Update: it suddenly started working, without any change on the server side. I think it was some kind of issue with caching, either in firefox, cloudflare or Nginx's part.

Writing data to JSON file using nodeJS takes too long

i am creating a function that Count the clicks of elements , and put them in JSON file
const fs = require('fs');
const file = fs.readFileSync('public/js/count.json');
const Words = JSON.parse(file);
const express = require('express');
const app = express();
app.listen(process.env.PORT || 3000, () => console.log('we are listeining'));
app.use(express.static('public'));
app.use(express.json({ limit : '1mb' }));
app.get('/add/:word', addWord);
function addWord(request, response) {
var data = request.params;
var word = data.word;
var reply;
var found = false;
for (i = 0; i < Words.length; i++){
if (Words[i].type == word){
Words[i].count++;
found = true;
break;
}
}
if (!found) {
Words.push({"type": word , "count": 1});
}
var x = JSON.stringify(Words, null, 2);
fs.writeFile('public/js/count.json', x, finished);
function finished(){
console.log('Yay')
}
/*
console.log(Words[word]); */
/* response.send(reply); */
}
when i run the code through my script
async function counter(elemid){
let response = await fetch("/add/"+elemid);
}
it takes too long to respond , and sometimes it gives request timeout , is there is a faster way to do the exact same purpose
You are not writing a response in your finished handler. This is leaving each request to only end via timeout.
In your finished function add response.end() at the end.
You can verify that this is working by ensuring that the request receives a 200 response from your server instead of timing out.

What is the best way to structure my data model in nodeJS

I have a route that sends to me many requests over time, that contain data to stored in a model.
So the first request does not contain all the needed data and I need to parse each request every time new information comes and store it.
Actually I have a separate js file which contains the "model" and methods
const request = require('request-promise');
function Conversation(param) {
console.log(param)
this.endpoint ;
this.id = this.getConvId(param);
this.createdOn = Date.now();
this.to = this.getTo(param);
this.from = this.getFrom(param);
this.state = this.getState(param);
this.importance = this.getImportance(param);
this.threadId = this.getT;
this.subject = this.getSubject(param);
this.name=this.getName(param);
}
Conversation.prototype.sendIM =function sendIM(param) {
// method to send message to a user
}
Conversation.prototype.getConvId = function getConvId(param) {
return param.operationId
};
Conversation.prototype.getTo = function getTo(param) {
return param.to
}
Conversation.prototype.getDirection = function getDirection(param) {
return param.direction
}
Conversation.prototype.getState = function getState(param) {
return param.state
}
Conversation.prototype.getOperationId = function getOperationId(param) {
return param.sender[0].events[0]._embedded["service:messagingInvitation"].opertionId
}
Conversation.prototype.getImportance = function getSubject(param) {
return param.importance;
}
Conversation.prototype.getSubject = function getSubject(param) {
return param.sender[0].events[0]._embedded["service:messagingInvitation"].subject
}
Conversation.prototype.getFrom= function getFrom(param) {
return param._embedded["localParticipant"].uri
}
Conversation.prototype.getName= function getName(param) {
return param._embedded["acceptedByParticipant"].name
}
module.exports = Conversation;
In my main app file I create a new conversation object:
var Conversation= require('./Conversation');
app.post('/callback', function (req, res) {
if(req.body.sender.length==0) {
res.status(200).send();
}
if(req.body.sender.length>0) {
const conv = new Conversation(req.body.sender[0].events[0]._embedded['service:messagingInvitation']);
res.status(200).send();
}
})
the method works well when I have to fill the model once, but when I update an item it becomes complicated.
So I would like to know what is the best way to structure my files so that I will be able to add new data to my model over time ?

Node.js & Express: How to create many app.get calls with Express.js through "for loop"?

In my server.js, I am trying to loop through the array, that has different urls and use those urls for app.get request function.
Here is my code:
let articleUrlArray = [ 'https://techcrunch.com/2018/05/19/shared-housing-startups-are-taking-off/',
'https://techcrunch.com/2018/05/19/shared-housing-startups-are-taking-off/',
'https://techcrunch.com/2018/05/19/my-data-request-lists-guides-to-get-data-about-you/',
'https://techcrunch.com/2018/05/19/siempos-new-app-will-break-your-smartphone-addiction/',
'https://techcrunch.com/2018/05/19/la-belle-vie-wants-to-compete-with-amazon-prime-now-in-paris/',
'https://techcrunch.com/2018/05/19/apple-started-paying-15-billion-european-tax-fine/',
'https://techcrunch.com/2018/05/19/original-content-dear-white-people/',
'https://techcrunch.com/2018/05/19/meet-the-judges-for-the-tc-startup-battlefield-europe-at-vivatech/',
'https://techcrunch.com/2018/05/18/nasas-newest-planet-hunting-satellite-takes-a-stellar-first-test-image/',
'https://techcrunch.com/video-article/turning-your-toys-into-robots-with-circuit-cubes/',
'https://techcrunch.com/2018/05/18/does-googles-duplex-violate-two-party-consent-laws/' ];
for(var i = 0; i < articleUrlArray.length-1; i++) {
app.get('/news/news-desc', function(req, res) {
var data = '';
var techCrunchNewsItems = [];
request( articleUrlArray[i], function(err, response, html) {
var $ = cheerio.load(html);
if($('.article-content').children('p').eq(0).text().split(' ').length > 50) {
techCrunchNewsItems.push({
bodyOne: $('.article-content').children('p').eq(0).text()
});
} else {
techCrunchNewsItems.push({
bodyOne: $('.article-content').children('p').eq(0).text(),
bodyTwo: $('.article-content').children('p').eq(1).text()
});
}
data = techCrunchNewsItems;
res.send(JSON.stringify(data));
});
})
}
As you can see in my code, I have an array call "articleUrlArray" and created "for loop" to loop through this array to get each "articleUrl". Then use that "articleUrl" for request function and get the body content for that url.
No matter whatever happens, I always "only" get the body content for the last url. It is not getting the body content for every urls in the "articleUrlArray".
What am I doing wrong?
Here is the screenshot of what I am getting after running Hugo Nasciutti's solution below:
const articleUrlArray = [
'https://techcrunch.com/2018/05/19/shared-housing-startups-are-taking-off/',
'https://techcrunch.com/2018/05/19/shared-housing-startups-are-taking-off/',
'https://techcrunch.com/2018/05/19/my-data-request-lists-guides-to-get-data-about-you/',
'https://techcrunch.com/2018/05/19/siempos-new-app-will-break-your-smartphone-addiction/',
'https://techcrunch.com/2018/05/19/la-belle-vie-wants-to-compete-with-amazon-prime-now-in-paris/',
'https://techcrunch.com/2018/05/19/apple-started-paying-15-billion-european-tax-fine/',
'https://techcrunch.com/2018/05/19/original-content-dear-white-people/',
'https://techcrunch.com/2018/05/19/meet-the-judges-for-the-tc-startup-battlefield-europe-at-vivatech/',
'https://techcrunch.com/2018/05/18/nasas-newest-planet-hunting-satellite-takes-a-stellar-first-test-image/',
'https://techcrunch.com/video-article/turning-your-toys-into-robots-with-circuit-cubes/',
'https://techcrunch.com/2018/05/18/does-googles-duplex-violate-two-party-consent-laws/'
];
const checkBody = res => (err, response, html) => {
const $ = cheerio.load(html);
const articleContent = $('.article-content').children('p')
const bodyOne = articleContent.eq(0).text()
const bodyTwo = articleContent.eq(1).text()
const isExtensive = bodyOne.split(' ').length > 50
res(isExtensive ? { bodyOne } : { bodyOne, bodyTwo })
}
const getArticle = article => new Promise(res => request(article, checkBody(res)))
app.get('/news/news-desc', (req, res) => {
Promise.all(articleUrlArray.map(getArticle)).then(data => res.send(JSON.stringify(data)))
})
What is really going on here is that I am using a function to bring an array of Promises and when all of them are solved, then, respond the request with the array of objects stringified. I took the liberty of implementing arrow functions and constants.

global variable is not accessible in firebase function

I declared a global array in index.js (firebase function). Once the code is deployed, this array is filled from firebase data.
I have two functions, in the first one (onTW) i made some changes to the array, and i'm just displaying it in the other function(onRemoveTW). The problem is I'm getting an empty array in the second function.
Here's my code.
var TWArray = [];
TWRef.once('value', function (snapshot) {
snapshot.forEach(function(childSnapshot) {
var name=childSnapshot.key;
var users = {};
var userNbr = 0;
TWRef.child(name).child('rm').once('value', function (snapshot2) {
snapshot2.forEach(function(childSnapshot2) {
userNbr++;
if(childSnapshot2.key=='a'){
users.a = childSnapshot2.val();
}
if(childSnapshot2.key=='b'){
users.b = childSnapshot2.val();
}
if(childSnapshot2.key=='c'){
users.c = childSnapshot2.val();
}
if(childSnapshot2.key=='d'){
users.d = childSnapshot2.val();
}
})
TWArray.push({
rmName:name,
users:users,
userNbr:userNbr
});
})
})
})
exports.onTW = functions.database
.ref('/Orders/TW/{requestId}')
.onWrite(event => {
const userKey = event.data.key;
const post = event.data.val();
if (post != null) {
var users={};
users.a=userKey;
TWArray.push({
rmName:userKey,
users:users,
userNbr:1
});
console.log(TWArray);
console.log("TWArray.length : "+TWArray.length);
}
});
exports.onRemoveTW = functions.database
.ref('/Orders/RemoveTW/{requestId}')
.onWrite(event => {
const userKey = event.data.key;
const post = event.data.val();
if (post != null) {
console.log("TWArray.length : "+TWArray.length);
}
})
Thanks in advance!
You cannot share data between functions by writing to global variables when using firebase-functions, because they intended to be stateless. As such, this functionality is not supported.
What you can do is write your data to firebase-database instead.

Categories

Resources