Am I Releasing my SQL Connection Correctly? - javascript

I have an app that does many API calls, but I release each and every connection like this?
app.put("/interview/create/questions/:lastEmployeeId", function (req, res) {
console.log("It is getting to the route");
const employee_id = req.body.lastEmployeeId;
const tableName = req.body.table;
connection.getConnection(function (err, connection) {
connection.query(
`INSERT INTO ${tableName} (employee_id)
VALUES (?)`,
[employee_id],
function (error, results, fields) {
if (error) throw error;
res.json(results);
console.log(`Interview has been created`);
}
);
connection.release();
});
});
Is this the correct way, because I'm getting a lot of inconsistent 502 and 503 errors. It feels to me like maybe it's running out of resources. The paths are correct, because sometimes they work, and sometimes they don't. It's random, so I can't figure out what to do.
Doesn't the connection.release() free up the resources? I currently have the max connections set to 50, which should be more than I need because only one person at a time will be using this, and there is a method where it makes 8 calls. I wouldn't mind some help refactoring this, but I still need this many calls I believe because I need it to create rows in 8 different tables. This long method below here is just taking a value entered in one table, and entering it as a reference in the 8 other tables.
createQuestions() {
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_general",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_culture",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
)
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_performance",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
)
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_policies",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
)
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_risk",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
)
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_strategy",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
)
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_rewards",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
)
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_workforce",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
);
}

You're releasing the connection before the query completes. This needs to be addressed:
app.put("/interview/create/questions/:lastEmployeeId", function (req, res) {
console.log("It is getting to the route");
const employee_id = req.body.lastEmployeeId;
const tableName = req.body.table;
connection.getConnection(function (err, connection) {
if (err) {
res.statusCode = 500;
res.send('DB connection could not be acquired.');
return;
}
connection.query(
`INSERT INTO ${tableName} (employee_id)
VALUES (?)`,
[ employee_id ],
function (error, results, fields) {
// throw here does nothing useful, it's inside a callback and
// the calling function may have terminated ages ago. You need
// to handle this error here and now.
if (error) {
res.statusCode = 500;
res.send('Nope!');
return;
}
res.json(results);
console.log(`Interview has been created`);
// Now you can release the handle
connection.release();
}
);
// Code here runs before the query can complete.
});
});
Think of your asynchronous program flow like this:
connection.getConnection(..., cbGC) executes and returns
** Long time passes
cbGC executes -> connection.query(..., cbQ) executes and returns
** Tiny eternity elapses
cbQ executes!
The time interval between calling a function that takes a callback and that callback actually executing can be significant, seconds or more, which means the calling function is not only dead, it is ancient history, probably garbage collected.
You need to organize your code around this principle of nesting anything that depends on that sequencing.

Related

API inserting "undefined" into path in my React App

I'm sure I probably have something simple to fix, but have tried and tried and cannot find it. I have several API calls that are working just fine. But I have made a new one, which I made by copy and pasting ones that worked, and just changing values and names. But this new one, gives me a 500 error.
The API path should be:
"http://localhost:3000/billingcalculator/create"
Instead, it is:
"http://localhost:3000/undefined/billingcalculator/create" <-- where is the undefined coming from?
It gives this error:
PUT http://localhost:3000/undefined/billingcalculator/create 500 (Internal Server Error)
It references the line in the call that says throw new Error() ; but I don't see what's wrong with that. I use that exact same code all over the place and it works fine everywhere else.
Call that works perfectly:
createHCA() {
fetch(API_URL + `/hca/create`, {
method: "PUT",
body: JSON.stringify({
client: this.state.client,
short: this.state.short,
}),
headers: { "Content-Type": "application/json" },
})
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
.then(() => this.getHCAid())
.then(() => this.getAllHCAs());
this.setState({ showHide: false});
}
And this is the call that creates the error and cannot reach my API routes:
createBillProject() {
fetch(API_URL + `/billingcalculator/create`, {
method: "PUT",
body: JSON.stringify({
client: this.state.client,
source: this.state.source,
projectName: this.state.projectName
}),
headers: { "Content-Type": "application/json" },
})
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
.then(() => this.getBillProjLastId());
}
The API route I'm trying to reach is this:
app.put("/billingcalculator/create", function (req, res) {
console.log("It is getting to the billing route");
const client = req.body.client;
const source = req.body.source;
const projectName = req.body.projectName;
console.log(`client: ${client}`);
console.log(`source: ${source}`);
console.log(`project name: ${projectName}`);
connection.getConnection(function (err, connection) {
connection.query(
`INSERT INTO billcalc_projects (client, source, project_name)
VALUES (?, ?, ?)`,
[client, source, projectName],
function (error, results, fields) {
connection.release();
if (error) throw error;
res.json(results);
console.log(`Billing Project has been created`);
}
);
});
});
Thanks in advance for your help. It must be something simple that I'm just missing. But I haven't been able to figure it out.

How do I send my response in a API Route in next js when my data is in a .then promise

I am using next js with axios, and I have a .then promise inside a .then. I want to respond to the api request with the data I grabbed but if I put the res in the .then it is unreachable, but I don't know how to get the data out of the .then. Normally with async await I return the value and create a variable to the function but this does not seem to work with .then.
here is my code
let data;
axios
.post(
"https://accounts.spotify.com/api/token",
serialize({
grant_type: "client_credentials",
}),
{
headers: {
Authorization: "Basic " + auth,
},
}
)
.then((res) => {
axios
.get(
`https://api.spotify.com/v1/search?q=${name}&type=episode&market=US`,
{
headers: {
Authorization: `Bearer ${res.data.access_token}`,
"Content-Type": "application/json",
},
}
)
.then(function (response) {
// handle success
console.log(response.data.episodes);
data = response.data.episodes;
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
})
.catch((err) => {
console.log(err);
});
res.status(200).json({ data: data });
Any help would be greatly appreciated thanks
The following fixed it
const data = axios
.post(
"https://accounts.spotify.com/api/token",
serialize({
grant_type: "client_credentials",
}),
{
headers: {
Authorization: "Basic " + auth,
},
}
)
.then((res) => {
const test = axios
.get(
`https://api.spotify.com/v1/search?q=${name}&type=episode&market=US`,
{
headers: {
Authorization: `Bearer ${res.data.access_token}`,
"Content-Type": "application/json",
},
}
)
.then(function (response) {
// handle success
// console.log(response.data.episodes);
return response.data.episodes;
})
.catch(function (error) {
// handle error
console.log(error);
});
return test;
})
.catch((err) => {
console.log(err);
});
const boy = async () => {
console.log("data", await data);
res.status(200).json({ data: await data });
};
boy();

Getting data from metaweather API to react page

I tried to use this metaweather API but it's not working. this is a react project and I'm tyring on localhost. plz, can anyone show me what am I doing wrong here?
const fetchWeatherData = async() =>{
fetch('https://www.metaweather.com/api/location/search/?lattlong=36.96,-122.02', {
method:'GET',
mode:'no-cors',
headers: {
'Content-Type': 'application/json',
},
})
.then(response => {
console.log('response',response);
return response.json();
})
.then(data => {
console.log('data',data);
})
.catch((err) => {
console.log(err)
})}
these are logs i got
You just didn't close the function with curly brackets, I have tested it and it works fine , just call the function fetchWeatherData
const fetchWeatherData = async() => {
fetch('https://www.metaweather.com/api/location/search/?lattlong=36.96,-122.02', {
method:'GET',
mode:'no-cors',
headers: {
'Content-Type': 'application/json',
},
})
.then(response => {
return response.json();
})
.then(data => {
console.log('data',data);
})
.catch((err) => {
console.log(err)
})
}
fetchWeatherData()

JavaScript Fetching Multiple Requests In An Order

I am trying to fetch multiple requests in an order in React. There are 3 requests,
first one gathering encoded information from backend
get token from authentication server
use api with the token.
All of them must be in order. But I am having difficulties because of async fetch function. I can't reach fetch's response outside of .then() block.
To solve it, I used await / async. But it caused another problem. My 3 requests must be in a sequencial order. When I use async, order gets broken.
Here is the code.
class App extends Component {
constructor() {
super();
this.state = { code: '', encoded: '', access_token: '', refresh_token: '' };
}
getCarDetails() {
const carId = '2F3A228F6F66AEA580'
var query = 'https://api.mercedes-benz.com/experimental/connectedvehicle/v1/vehicles/'.concat(carId).concat('/doors')
fetch(query, {
method: 'GET',
headers: {
'Authorization': 'Bearer '.concat(this.state.access_token),
'accept': 'application/json'
}
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err));
}
getToken() {
var post_data = {
grant_type: 'authorization_code',
code: this.state.code,
redirect_uri: 'http://localhost'
}
fetch('https://api.secure.mercedes-benz.com/oidc10/auth/oauth/v2/token', {
method: 'POST',
headers: new Headers({
'Authorization': 'Basic '.concat(this.state.encoded),
'Content-Type': 'application/x-www-form-urlencoded'
}),
body: queryString.stringify(post_data)
})
.then(res => res.json())
.then(data => this.setState({ access_token: data.access_token, refresh_token: data.refresh_token }))
.catch(err => console.log(err));
}
getEncodedClientIdAndClientSecret() {
if (this.state.code != null) {
fetch('http://localhost:8000/encodeClientIdAndSecret', {
method: 'POST'
})
.then(res => res.json())
.then(data => this.setState({ encoded: data.encoded }))
.catch(err => console.log(err));
}
}
componentDidMount() {
const values = queryString.parse(this.props.location.search)
this.setState({ code: values.code })
console.log(this.state)
this.getEncodedClientIdAndClientSecret();
console.log(this.state) //this state is empty
//this.getToken();
//this.getCarDetails();
}
AWAIT / ASYNC
async getEncodedClientIdAndClientSecret() {
if (this.state.code != null) {
const response = await fetch('http://localhost:8000/encodeClientIdAndSecret', {
method: 'POST'
})
const data = await response.json();
console.log(data)
}
}
If I put await / async, I am having sequence problem between 3 requests.
in order to use async await on methods like
await getEncodedClientIdAndClientSecret();
await getToken();
you need to first return a promise from those functions like:
getToken() {
var post_data = {
grant_type: 'authorization_code',
code: this.state.code,
redirect_uri: 'http://localhost'
}
return fetch('https://api.secure.mercedes-benz.com/oidc10/auth/oauth/v2/token', {
method: 'POST',
headers: new Headers({
'Authorization': 'Basic '.concat(this.state.encoded),
'Content-Type': 'application/x-www-form-urlencoded'
}),
body: queryString.stringify(post_data)
})
.then(res => res.json())
.then(data => this.setState({ access_token: data.access_token, refresh_token: data.refresh_token }))
.catch(err => console.log(err));
}
so it can wait for the promise to finish, othewise they will run in parallel and finish in random order.

Async/Await in fetch() how to handle errors

I have stripe async code in my React app, and trying to add error handling in my code but have no idea how to handle it. i know how to do it with .then() but async/await is new to me
EDITED
added .catch() i got errors in network tab in response tab.
but i can log it to console?
submit = async () => {
const { email, price, name, phone, city, street, country } = this.state;
let { token } = await this.props.stripe
.createToken({
name,
address_city: city,
address_line1: street,
address_country: country
})
.catch(err => {
console.log(err.response.data);
});
const data = {
token: token.id,
email,
price,
name,
phone,
city,
street,
country
};
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).catch(err => {
console.log(err.response.data);
});
console.log(response);
if (response.ok)
this.setState({
complete: true
});
};
thanks
Fetch detects only network errors. Other errors (401, 400, 500) should be manually caught and rejected.
await fetch("/charge/pay", headers).then((response) => {
if (response.status >= 400 && response.status < 600) {
throw new Error("Bad response from server");
}
return response;
}).then((returnedResponse) => {
// Your response to manipulate
this.setState({
complete: true
});
}).catch((error) => {
// Your error is here!
console.log(error)
});
If you are not comfortable with this limitation of fetch, try using axios.
var handleError = function (err) {
console.warn(err);
return new Response(JSON.stringify({
code: 400,
message: 'Stupid network Error'
}));
};
var getPost = async function () {
// Get the post data
var post = await (fetch('https://jsonplaceholder.typicode.com/posts/5').catch(handleError));
// Get the author
var response = await (fetch('https://jsonplaceholder.typicode.com/users/' + post.userId).catch(handleError));
if (response.ok) {
return response.json();
} else {
return Promise.reject(response);
}
};
You can either use try/catch just like normal, imperative programming:
try {
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
} catch(error) {
// Error handling here!
}
Or you can mix-and-match .catch() just like you do with promises:
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).catch(function(error) {
// Error handling here!
});
Wrap your await with try catch.
try {
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
console.log(response);
} catch (error) {
console.log(error);
}
This works if server returns { message: "some error" } but I'm trying to get it to support res.statusText too:
const path = '/api/1/users/me';
const opts = {};
const headers = {};
const body = JSON.stringify({});
const token = localStorage.getItem('token');
if (token) {
headers.Authorization = `Bearer ${token}`;
}
try {
const res = await fetch(path, {
method: opts.method || 'GET',
body,
headers
});
if (res.ok) {
return await (opts.raw ? res.text() : res.json());
}
const err = await res.json();
throw new Error(err.message || err.statusText);
} catch (err) {
throw new Error(err);
}
async function loginWithRedirect(payload: {
username: string;
password: string;
}) {
const resp = await (await fetch(`${env.API_URL}/api/auth/login`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(payload),
credentials: "include",
})).json();
if (resp.error) {
dispatch({type: "ERROR", payload: resp.error.message});
} else {
dispatch({type: "LOGIN", payload: resp});
}
}
If response.ok is false you can throw an error then chain catch method after calling your function as follows
async function fetchData(){
const response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
if(!response.ok){
const message = `An error occured: ${response.status}`;
throw new Error(message);
}
const data = await response.json();
return data;
}
fetchData()
.catch(err => console.log(err.message));
I write promise function for using fetch in async await.
const promisyFetch = (url, options) =>
new Promise((resolve, reject) => {
fetch(url, options)
.then((response) => response.text())
.then((result) => resolve(result))
.catch((error) => reject(error));
});
By the way i can use it easly in async with try catch
const foo = async()=>{
try {
const result = await promisyFetch('url' requestOptions)
console.log(result)
} catch (error) {
console.log(error)
}
}
It was simple example, you could customize promisyFetch function and request options as you wish.
const data = {
token: token.id,
email,
price,
name,
phone,
city,
street,
country
};
axios
.post("/charge/pay", data)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err.response.data);
});

Categories

Resources