Express fetching data promise is pending - javascript

I've written 2 snippets of code - client and server. When the client clicks the button he sends information to the server, which uses the Riot API to retrieve summoner info. Now I want to send it back to the client but once I fetch it my promise response is pending and result is undefined. Promises are a new thing for me. Here's the code,
Client:
<!DOCTYPE html>
<html>
<head>
<script>
function sendInfo(){
let name = document.getElementById("checker").value;
let data = {name};
fetch("/api", {
method: "POST",
headers: {
"Content-type": "application/json"
},
body: JSON.stringify(data)
});
//let data = document.getElementById("levelID");
fetch("/level", {
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(function(res){
console.log(res.json());
})
.then(function(data){
console.log(data);
})
.catch(function(error){
console.log(error);
});
}
</script>
</head>
<body>
<input type="text" name="checkPlayer" id="checker"><br>
<button onclick="sendInfo()">Search summoner!</button>
</body>
</html>
Server:
const PORT = 3000;
const axios = require("axios");
const express = require("express");
const path = require('path');
const key = "RGAPI-50e38ac8-4629-4abc-aef9-68e4259448bd";
const parser = require("body-parser");
var jsonParser = parser.json();
//let puuid, summonerID, level;
let summoner;
const app = express();
app.listen(PORT, () => {
console.log("listening at 3000");
});
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, '/main.html'));
//searchBySummonerName("RnkzOnFire");
});
app.post("/api", jsonParser, (req, res) => {
searchBySummonerName(req.body.name);
});
app.get("/level", (req, res) => {
res.writeHead(200, {"Content-Type": "application/json"});
res.write(JSON.stringify(summoner));
});
function searchBySummonerName(name){
const searchURL = "https://eun1.api.riotgames.com/lol/summoner/v4/summoners/by-name/" + name + "?" + "api_key=" + key;
axios.get(searchURL).then((res) => {
summoner = res.data;
});
}

Related

POST Request Returns Empty First TIme, Then Isn't empty every time after

For Some Reason, The POST request for a link below returns empty the first time and then isn't empty every time after. If I change the email and make a new request, it returns the last user called for. It seems that the array is retaining its value on the server. I used the array because a global variable wasn't being defined by the promise chain from the fetch call. Below is the code for the server, as well as the request from Postman. I think this can be solved by figuring out how to define the global var in the fetch call, but every solution I've researched has failed.
Server Side Code:
//add in external libraries and requirements
const dotenv = require('dotenv')
dotenv.config({ path: './.env' })
const express = require('express')
const app = express()
const port = process.env.PORT || 8080
var cors = require('cors')
const fs = require('fs')
const fetch = require("node-fetch");
var bodyParser = require('body-parser')
let resultarr = []
let resultarr1 = []
//encryption
const key = process.env.KEY
function fakeMathRandom(callBack) {
if(!callBack) throw new Error("Must provide callBack function");
let seed=0;
const randomOutputs = [0.04,0.08,0.15,0.16,0.23,0.42,0.52,0.65,0.79,0.89];
const Math_random = Math.random;
Math.random = function() {return randomOutputs[seed++ % 10];}
const callbackOutput = callBack();
Math.random = Math_random;
return callbackOutput;
}
// create application/json parser
var jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
//serve static files
var publicdir = __dirname + '/public';
app.use(function(req, res, next) {
console.log(req)
if (req.path.indexOf('.') === -1) {
var file = publicdir + req.path + '.html';
fs.exists(file, function(exists) {
if (exists)
req.url += '.html';
next();
});
}
else
next();
});
app.use(cors())
app.use(express.static(publicdir));
// POST request
app.post('/email', jsonParser, function (req, response) {
var email = (req.body.email)
var password = (req.body.password)
var result;
var url = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyC-BUGGSsvUX8z4W1LcsJzS59yrL4__EsE";
var payload = {
email: email,
password: password,
returnSecureToken: true
};
var options = {
method: 'post',
contentType: 'application/json',
body: JSON.stringify(payload)
};
//make fetch call
load =(url, options) =>{
return fetch(url, options).then(response => response.json());
}
load(url,options).then(result => {
// result is the parsed JSON - i.e. a plan ol' javascript object
resultarr[0] = result
});
response.send(resultarr[0])
})
app.get('/test', (req, res) => {
res.send(resultarr[0]);
});
app.listen(port, () => {
console.log(`app listening at port:${port}`)
});
Postman API Request (Curl)
curl --location --request POST 'https://splurket.us/email' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "testuser#gmail.com",
"password": "Testing123",
"returnSecureToken": true
}'
Emails You Can use For Testing The Endpoint:
Email: Testinguser#gmail.com | Password: Testing123
Email: Testinguser1#gmail.com | Password: Testing123
I solved the problem. So In Express, you can just use the async function shown below and then you can use await since it is inside an async function.
app.post('/email', jsonParser, async function (req, response) {
var email = req.body.email
var password = req.body.password
var result;
var url = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyC-BUGGSsvUX8z4W1LcsJzS59yrL4__EsE";
var payload = {
email: email,
password: password,
returnSecureToken: true
};
var options = {
method: 'post',
contentType: 'application/json',
body: JSON.stringify(payload)
};
const res = await fetch(url, options);
const result = await res.json();
response.send(result)
})

I'm getting empty request body in express.js

I'm trying to get my data in my database but not getting anything in the body of the request. I have used parse-body and CORS but it still not working.
I tried several things but did not work.
Backend code:
const bodyParser = require('body-parser');
const cors = require('cors');
const port = 5000;
const app = express();
app.use(cors());
app.use(bodyParser.json());
const MongoClient = require("mongodb").MongoClient;
const uri = "mongodb+srv://ishadDB#cluster0.gi4fd.mongodb.net/?retryWrites=true&w=majority";
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
client.connect((err) => {
const bookings = client.db("BurjAlArab").collection("bookings");
console.log("Connected");
app.post('/addBooking', (req, res) => {
console.log(req)
const newBooking = req.body;
console.log(newBooking);
bookings.insertOne(newBooking)
.then(res => {
res.send(result.insertedCount > 0);
});
});
});
app.get("/", (req, res) => {
res.send("Hello World!");
});
app.listen(port);
front end:
const handleBooking = () => {
const newBooking = { ...loggedInUser, ...selectedDate };
fetch('http://localhost:5000/addBooking', {
method: 'POST',
header: { 'Content-Type' : 'application/json' },
body : JSON.stringify({newBooking})
})
.then((res) => res.json())
.then((data) => {
console.log(data);
});
};
Can anyone help me out?
Try to send it in your frontend with the following code
This take use of await
Notice because of the use of await the function have to be async
async function bla(){}
async function bla(){
const data = {newBooking};
const options = {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data)
};
await fetch('/addBooking', options);
}
}

How to increment property in MongoDB collection using $inc

I have a list of articles that have a property views and I want to increment that property in the database each time a user clicks on an article title. Currently nothing happens when I do it. Why isn't it working and how can I increment that property each time on click? Here is my React part:
const incrementViews = (id) => {
var item = posts.find(x => x._id === id);
item.views += 1;
}
<div className="post-title">
<Link to={`/post/${post._id}`}>
<h2><a href="#" onClick={() => incrementViews(post._id)}>{post.title}</a>
</h2>
</Link>
</div>
and my server.js:
// Requiring the dependencies
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
require('dotenv').config();
const mongoose = require('mongoose');
const PORT = process.env.PORT || 3001;
const BASE_URL = process.env.REACT_APP_BASE_URL;
console.log(BASE_URL)
const itemRoutes = express.Router();
let Comment = require('./comment.model');
app.use(cors());
app.use(bodyParser.json());
mongoose.connect(BASE_URL, { useNewUrlParser: true })
const connection = mongoose.connection;
connection.once('open', function () {
console.log('Connection to MongoDB established succesfully!');
});
let collection = connection.collection("posts_with_tags_test");
collection.createIndex(
{
postContent: 'text',
title: 'text'
}
);
// Serve static assets
if (process.env.NODE_ENV === 'production') {
app.use(express.static('build'));
}
itemRoutes.route('/').get(async (req, res) => {
let collection = connection.collection("posts_with_tags_test");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/search').post(async (req, res) => {
let result = await connection.collection("posts_with_tags_test").find({
$text: {
$search: req.body.searchString
}
}).toArray();
res.send(result);
});
itemRoutes.route("increment/:id"").post(async (req, res) => {
const { id } = req.params;
collection.updateOne({ _id: id }, { $inc: { views: 1 } });
return res.status(200).json({ msg: "OK" });
});
itemRoutes.route('/comments').get(async (req, res) => {
let collection = connection.collection("comments");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/comments')
.post((req, res) => {
res.setHeader('Content-Type', 'application/json');
let comment = new Comment(req.body);
comment.save()
.then(comment => {
res.status(200).json({ comment })
})
.catch(err => {
res.status(400).send('failed')
})
});
app.use('/', itemRoutes);
app.use('/comments', itemRoutes);
app.use('/search', itemRoutes);
app.use('/increment', itemRoutes);
app.listen(PORT, function () {
console.log('Server is running on' + ' ' + PORT);
})
I think there are two problems in frontend and backend respectively.
Front-end
You should use post variable as a state variable so as to re-render then component when changes are made on post.
Back-end
There is no issue with increasing view in your code.
Here, you need to return success status.
The function incrementViews only increments views on the frontend and never sends any data to the API. One way you can make it work is as follows:
server.js
itemRoutes.route("/increment/:id").post(async (req, res) => {
const { id } = req.params;
collection.updateOne({ _id: id }, { $inc: { views: 1 } });
return res.status(200).json({ msg: "OK" });
});
React
const incrementViews = (id) => {
// Assuming your API server is running on port 5000.
fetch(`http://localhost:5000/increment/${id}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((res) => res.json())
.then(console.log)
.catch(console.error);
};
Update
The reason you're getting 404 is a missing colon : in the route parameters.
// Notice the :id, colon is important.
itemRoutes.route("/increment/:id").post(async (req, res) => {
const { id } = req.params;
// ...
});
Here is a demo reproduced on Glitch. Removed database logic and just added a response messages.
I tested the demo using Postman and it works fine.
On a POST request to https://adaptive-sassy-legal.glitch.me/increment/123, should return a response as shown below.
{
msg: "itemsRoute increment.",
id: "123"
}
Update 2
Another thing which I forgot to mention in the previous update was to update the middleware.
// Use only `/increment` instead of `increment/:id`.
app.use("/increment", itemRoutes);
Here is an updated demo.

node js TypeError: Cannot read property 'body' of undefined

I'm working on an example project for a Udacity course and I'm tripped up with something. I'm trying to capture some user input from a form and make a post request to return a javascript object and when I try to run the server with node js, I get the error:
TypeError: Cannot read property 'body' of undefined
This is the server code for the project:
server.js
projectData = {};
/* Express to run server and routes */
const express = require('express');
/* Start up an instance of app */
const app = express();
/* Dependencies */
const bodyParser = require('body-parser')
/* Middleware*/
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const cors = require('cors');
app.use(cors());
/* Initialize the main project folder*/
app.use(express.static('project1'));
const port = 8000;
/* Spin up the server*/
const server = app.listen(port, listening);
function listening(){
// console.log(server);
console.log(`running on localhost: ${port}`);
};
// GET route
const animalData = [];
app.get('/all', getData);
function getData(req, res){
res.send(AnimalData)
console.log(AnimalData)
}
// function sendData (request, response) {
// response.send(projectData);
// };
// POST route
app.post('/add', callBack);
function callBack(req,res){
res.send('POST received');
}
// POST an animal
const data = [];
// TODO-Call Function
app.route('/addAnimal')
.get(function (req, res) {
res.sendFile('index.html', {root: 'project1'})
})
.post(addAnimal())
function addAnimal(req, res){
newEntry = {
animal: req.body.animal,
facts: req.body.fact,
fav: req.body.fav
}
data.push(req.body);
res.status(200).send(req.body);
animalData.push(newEntry)
res.send(animalData)
console.log(animalData)
};
and this is the code for the client side:
app.js
function performActuion(e){
const fav = document.getElementById('fav').value;
const getAnimal = async (url) =>{
const res = await fetch(url);
try {
const data = await res.json();
console.log(data)
return data;
} catch(error) {
console.log()
}
};
/* Function to POST data */
const postData = async ( url = '', data = {})=>{
console.log(data);
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
});
try {
const newData = await response.json();
console.log(newData);
// console.log(newData);
return newData.json()
console.log(await response.json());
return await response.json()
}catch(error) {
console.log("error", error);
// appropriately handle the error
};
};
// TODO-Call Function
(async function(){
let res = await postData('/addAnimal', (animal: data.animal, fact: data.fact, fav: fav));;
console.log(res);
})();
In the example for the lesson, this code appears to work but when I try to run it on my end I can't even test it because I get that type error. Any help would be greatly appreciated.
Thank you,
Mike
The problem is in this code:
app.route('/addAnimal')
.get(function (req, res) {
res.sendFile('index.html', {root: 'project1'})
})
.post(addAnimal())
You are actually calling the function instead of use it as callback, use the following code:
app.route('/addAnimal')
.get(function (req, res) {
res.sendFile('index.html', {root: 'project1'})
})
.post(addAnimal)

How to send a POST request from node.js Express?

Could someone show me the simplest way to send a post request from node.js Express, including how to pass and retrieve some data? I am expecting something similar to cURL in PHP.
var request = require('request');
function updateClient(postData){
var clientServerOptions = {
uri: 'http://'+clientHost+''+clientContext,
body: JSON.stringify(postData),
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
}
request(clientServerOptions, function (error, response) {
console.log(error,response.body);
return;
});
}
For this to work, your server must be something like:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json())
var port = 9000;
app.post('/sample/put/data', function(req, res) {
console.log('receiving data ...');
console.log('body is ',req.body);
res.send(req.body);
});
// start the server
app.listen(port);
console.log('Server started! At http://localhost:' + port);
As described here for a post request :
var http = require('http');
var options = {
host: 'www.host.com',
path: '/',
port: '80',
method: 'POST'
};
callback = function(response) {
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
}
var req = http.request(options, callback);
//This is the data we are posting, it needs to be a string or a buffer
req.write("data");
req.end();
you can try like this:
var request = require('request');
request.post({ headers: {'content-type' : 'application/json'}
, url: <your URL>, body: <req_body in json> }
, function(error, response, body){
console.log(body);
});
in your server side the code looks like:
var request = require('request');
app.post('/add', function(req, res){
console.log(req.body);
request.post(
{
url:'http://localhost:6001/add',
json: {
unit_name:req.body.unit_name,
unit_price:req.body.unit_price
},
headers: {
'Content-Type': 'application/json'
}
},
function(error, response, body){
// console.log(error);
// console.log(response);
console.log(body);
res.send(body);
});
// res.send("body");
});
in receiving end server code looks like:
app.post('/add', function(req, res){
console.log('received request')
console.log(req.body);
let adunit = new AdUnit(req.body);
adunit.save()
.then(game => {
res.status(200).json({'adUnit':'AdUnit is added successfully'})
})
.catch(err => {
res.status(400).send('unable to save to database');
})
});
Schema is just two properties unit_name and unit_price.
I use superagent, which is simliar to jQuery.
Here is the docs
And the demo like:
var sa = require('superagent');
sa.post('url')
.send({key: value})
.end(function(err, res) {
//TODO
});
Try this. It works for me.
const express = require("express");
const app = express();
app.use(express.json());
const PORT = 3000;
const jobTypes = [
{ id: 1, type: "Interior" },
{ id: 2, type: "Etterior" },
{ id: 3, type: "Roof" },
{ id: 4, type: "Renovations" },
{ id: 5, type: "Roof" },
];
app.post("/api/jobtypes", (req, res) => {
const jobtype = { id: jobTypes.length + 1, type: req.body.type };
jobTypes.push(jobtype);
res.send(jobtype);
});
app.listen(PORT, console.log(`Listening on port ${PORT}....`));

Categories