I have been trying to complete this past paper but Im not sure if im on the right lines as to my solution and so wanted some help to see if I am on the right track or whether I need some guidance on getting there!
the question is as follows:
You have been contracted to write part of a RESTful web API for products on an e-commerce platform using Node.js. Another developer had previously been working on the project and had written the following tests using Mocha and Chai.
const expect = require('chai').expect;
const request = require('superagent');
const status = {OK:200,BADREQUEST:400};
const endpointURL =
'http://localhost:3000/api/v1/products/';
describe('Products APIT,function(){
/* Details of below data unnecessary to answer question */
const validId = /* ID of product already in database */;
const invalidId = /* Invalid product ID */;
const validProduct = {/* Valid product object*/};
it('valid GET requests',function(done){
request.get(apiRoot + validId).end(function(err,res){
expect(res.statusCode).to.equal(status.OK);
expect(res.body).to.have.property('price');
expect(res.body).to.have.property('quantity');
done();
});
});
it('invalid GET requests',function(done){
request.get(apiRoot + invalidId).end(function(err,res){
expect(res.statusCode).to.equal(status.BAD_REQUEST);
done();
});
});
it('valid PUT requests',function(done){
request.put(endpointURL + validId).send(validProduct)
.end(function(err,res){
expect(res.statusCode).to.equal(status.OK);
expect(res.body).to.deep.equal(validProduct);
request.get(apiRoot + validID).end(function(err,res){
expect(res.body.price).to.equal(validProduct.price);
expect(res.body.quantity)
.to.equal(validProduct.quantity);
done();
});
});
});
The tests also partially specify the behaviour of the API when responding to a PUT request. It should be possible to update an existing product to take a new (valid) value by making a PUT request to the path /api/vl/products/ followed by the product ID (e.g. /api/vl/products/42 for the product with ID 42). The response to a successful update should have status code 400 (OK) and the body of the response should contain the updated product. Updating the product should not change its ID.
Below is a partial implementation of the API using the express framework
var express = require('express');
var app = express();
var products = require('./lib/products');
app.getC/api/v1/products/:idP,function(req,res,next){
const id = req.params._id;
/*i) Complete for question i) here */
} ) ;
app.putC/api/v1/products/:idP,function(req,res,next){
const id = req.params._id;
/*ii) Complete for question ii) here */
} ) ;
var port = 3000;
app.listen(port,function(){
console.log('Listening on port ' + port);
});
where the products variable contains a data layer with the following methods:
Method Signature
Description
Result
read(id,callback)
reads product with
Product
specified id.
with
specified id
---------------------------
--------------------
------------
update(id,product,callback)
updates product with
updated
specified id to have
product.
value of parameter
product.
In both of these cases, callback will be a function to be called after the database operation has completed (successfully or unsuccessfully) with two arguments. The first argument will be an error object (null if and only if the operation has completed without errors). The second argument will be a result object containing the result of a successfully completed operation as described in the table above.
i) Complete the code above such that the API responds to GET requests as specified in the tests.
ii) Complete the code above such that the API responds to PUT requests as specified in the tests.
I have placed my attempt at question i) here below:
product.read(id,function(err,res)){
if(res.status(status.OK)
return res.sendStatus(status.OK);
return res.body('price' && 'quantity');
if(res.status(status.BAD_REQUEST))
return res.sendStatus(status.BAD_REQUEST);
}
but for ii) im afraid my brain just literally CRASHES, im new to node.js and js so please dumb down the explanation as much as you can for me!! Thank you i very much will appreciate all help since i am a beginner and im finding it hard to wrap my head around this question! Lecture notes do not seem to help much :((
Related
A new message gets inserted into the mongoDB from another application that I don't have access to the code. I do have the database credentials though. I want to make that message show on my application at the moment it gets inserted into mongoDB. I don't want to loop. I want to show the new data the moment it gets Inserted or Updated.
A living example: Auction websites generally update the newest bids really quickly, a few seconds before the auction deadline ends. I am wondering how that works without loops. Like a chat app, but waiting for new data in the database instead of another user typing a message. But in my situation, the data gets Inserted or Updated by another application.
Some additional information: I am also using routers / express and hbs html template. I am happy enough if I get atleast a general idea of how to do this, without working with routers / express yet. But if you guys can come up with a combined solution that would be perfect!
I have something like this so far but it's still a bit confusing. You can pretty much ignore my code since it's not working completely. But maybe it helps a bit.
(some more code above ...)
const WebSocketServer = new WebSocket.Server({port: 8082})
WebSocketServer.on('connection', ws => {
console.log('New client connected!')
ws.on('message', async (data) => {
console.log(`Client has sent us: ${data}`)
const connMtlinki = require('../src/db/mtlinki')
const connection = connMtlinki.connect()
const database = connMtlinki.db('MTLINKi')
const MacroVariableHistory = database.collection('MacroVariableHistory')
const machines = await MacroVariableHistory.findOne({ L0Name: data })
console.log(machines)
ws.send(machines)
})
ws.on('close', () => {
console.log('Client has disconnected!')
})
I am new to programming, and I heard that some guys on this website are quite angry, but please don't be. I am creating one web app, that has a web page and also makes som ecalculations and works with database (NeDB). I have an index.js
const selects = document.getElementsByClassName("sel");
const arr = ["Yura", "Nairi", "Mher", "Hayko"];
for (let el in selects) {
for (let key in arr) {
selects[el].innerHTML += `<option>${arr[key]}</option>`;
}
}
I have a function which fills the select elements with data from an array.
In other file named: getData.js:
var Datastore = require("nedb");
var users = new Datastore({ filename: "players" });
users.loadDatabase();
const names = [];
users.find({}, function (err, doc) {
for (let key in doc) {
names.push(doc[key].name);
}
});
I have some code that gets data from db and puts it in array. And I need that data to use in the index.js mentioned above, but the problem is that I don't know how to tranfer the data from getData.js to index.js. I have tried module.exports but it is not working, the browser console says that it can't recognize require keyword, I also can't get data directly in index.js because the browse can't recognize the code related to database.
You need to provide a server, which is connected to the Database.
Browser -> Server -> DB
Browser -> Server: Server provides endpoints where the Browser(Client) can fetch data from. https://expressjs.com/en/starter/hello-world.html
Server -> DB: gets the Data out of the Database and can do whatever it want with it. In your case the Data should get provided to the Client.
TODOs
Step 1: set up a server. For example with express.js (google it)
Step 2: learn how to fetch Data from the Browser(Client) AJAX GET are the keywords to google.
Step 3: setup a Database connection from you Server and get your data
Step 4: Do whatever you want with your data.
At first I thought it is a simple method, but them I researched a little bit and realized that I didn't have enough information about how it really works. Now I solved the problem, using promises and templete engine ejs. Thank you all for your time. I appreciate your help)
I am developing a Node.JS application in which I have an endpoint as shown below:
const streamService = require('./stream.service');
module.exports = function (app) {
/**
* Below API will send all streams data according to the parameters passed in query parameters.
*/
app.get("/streams", async function (request, response) {
var device_id = (!req.query.device_id) ? "" : req.query.device_id;
var userid = (!req.query.user) ? "" : req.query.user;
var streams = streamService.getAllStreams(device_id,userid);
response.send(streams);
});
}
This calls getAllStreams function which is written in some other file. While the function getAllStreams is getting executed if any other API hit comes then it is overriding the data which I am getting from query parameters and affecting the response of 'getAllStreams' function. I have also observed that the response is a mixture of both the API calls expected result. I am willing to know if I am doing anything wrong while calling function. Basically it should create a new instance of that function for every call but it is not creating.
I know this is a very strange behavior of JavaScript I have noticed today. I have never ever expected that but I am looking for any solution. Please note that I have checked the above said scenario multiple times by putting some logs at both server and client side.
Thank you in advance for your help. :-)
Note:
The asynchronous nature of firebase has been discussed thousands of times here, but my low reputation number does not allow for a comment on an existing question. That's why I have asked this question.
I am a noob, so please help me understand the implementation in an easy to understand manner.
Steps to implement:
User enters a value in the HTML input box
Search the input value in the firebase db (showMessage() gets called)
Display an appropriate result based on the search result in step 2
Problem faced:
The message displayed in step 3 takes almost an average of 1.75 seconds to display. This experience is not user-friendly. I want to display the message as soon as possible i.e. want to reduce the fetch time.
Probable root causes:
Either my way of fetching the data from firebase dB is incorrect (I still don't understand how to keep a promise :()
Or The mechanism of search and display is not right
var full_name;
function showMessage(){
extractData();
}
function extractData(){
test(function(returnValue) {
custom_message = searchMessage(returnValue);
var container = document.querySelector('#placeholder');
var para = document.createElement('p');
var custom_message = "Happy happy, buds!";
para.innerHTML = custom_message;
para.className = "message";
container.appendChild(para);
});
}
function test(callback) {
var ref = firebase.database().ref();
ref.on('value', function(snapshot) {
var data = snapshot.val();
callback(data);
}, function (error) {
console.log("Error: " + error.code);
});
}
function searchMessage(data){
for(var i = 0; i < data.length; i++)
{
name_f_data = data[i].firstName.concat(" ", data[i].lastName);
if(full_name.toLowerCase() == name_f_data.toLowerCase())
{
console.log(name_f_data.toLowerCase());
console.log(full_name.toLowerCase());
return data[i].message;
}
}
}
The time a read operation takes depends on:
The latency of your connection to Firebase's servers
The amount of data you are reading
The bandwidth of your connection
The time it takes Firebase to process the request
In most cases, the time Firebase takes is only a very small portion of the total time, and most of your time actually goes to the data transfer, which depends purely on the bandwidth and amount of data. If this is the first time you're reading data from Firebase in the page, the latency also matters more, as Firebase has to establish a connection, which takes a few roundtrips.
Your current code is downloading all data from the database, and then searching in the JavaScript code for a child node that matches a certain value. The best way to reduce the time that takes (apart from upgrading to a fast connection) is to transfer less data, which you can do by using Firebase's query mechanism to do the filtering on the server.
You can get pretty close with:
var ref = firebase.database().ref();
var query = ref.orderByChild().startAt(firstName).endAt(firstName+"~");
query.once('value', function(snapshot) {
var data = snapshot.val();
callback(data);
This will significantly reduce the amount of data transferred. A few notes though:
The query returns just the people that have the first name you're looking for. It does not yet filter on the last name, so you'll still need to filter that in the client-side code.
To further optimize this, store the full name (which you now compose in the client-side code) in the database so that you can query on that and reduce data transfer even more.
Firebase queries are case sensitive, so the query only returns data where the case matches exactly. If you want to query case-indifferent, consider storing a toLowerCase() value in the database.
Be sure to define an index on firstName, as otherwise the Firebase database will still send all data to the client, and the SDK will perform the filtering client-side.
I'm working on a section of my app where a user can add a note to his project. Each note has the capability to have additional comments appended to it.
So far the backend is working. When calling all records at a time or one record at a time(by id) manually, be it via postman or simply adding the id number of a project(gotten from mongo) to the browser, both pull up the records as specified.
The problem starts when I try to pull this information through the front end via
$.getJSON.
Say for example that I have two projects in my app.
Project 01 has an id of "123" and has 3 comments
and
Project 02 has an id of "456" and has 10 comments
When I call all projects on the front end of the app, I see both appear, and all their comments come through ok but when I try to call, for example, project two by id, it does show but I get 10 "undefined" for all of that projects 10 comments. Same thing happens for any one record I call.
And again, this happens only when trying to call it via jquery $.getJSON because when I manually do it via postman/browser, they come through fine.
Here is some code below for when I try to find one record (not working fully).
This is the backend code:
app.get("/notesapi/:tabID", (request, response) => {
var idNum = request.params.tabID;
var newIdNumber = idNum.trim();
NotesModel.findOne({_id: newIdNumber}, (error, data)=>{
if(error){
console.log("error in finding this particular record!");
throw error;
} else {
console.log("data for this one record found YO");
response.status(200);
response.json(data);
}
});
});
And this is the front end code:
function getFreshComments(tabID){
console.log("FRONTEND -- the link is: /notesapi/" + tabID);
$.getJSON("/notesapi/456", showCommentsGotten);
function showCommentsGotten(dataFedIn){
var tabInnerComments = $("#" + tabID +" .theNote");
var output = "";
$.each(dataFedIn, (key, item)=>{
output += item.todoMessages + "<br>";
});
var normalComments = output;
var newComments = normalComments.split(",").join("<br>");
tabInnerComments.html(newComments);
}
}
As the example explained above, if I wanted to pull the 10 comments from id 456, then when I use $.getJSON("/notesapi/456", showCommentsGotten);
This returns me 10 "undefined".
When I remove the id number from the URL, then it fetches me ALL the comments for ALL the notes.
I don't get any errors anywhere. What am I missing or doing wrong?