I am trying to build a log for an Express API, however am having issues getting the data to log out.
I can log the original req and res objects in the finally block, but am not sure how I would access the SQL response.
const sql = require("mssql")
const config = require("../config")
router.get("/express-route", (req, res) => {
sql.connect(config.properties).then(pool => {
return pool.request()
.input('username', sql.NVarChar(32), req.params.username)
.execute('do_something_with_username')
.then(response => res.send(response) // pass this response
.catch(err => res.send(err))
.finally(() => {
console.log('response', response) // to here
sql.close()
})
})
}
How would I take the response from the first then block and pass it to the finally block to be used in another function?
A finally callback will not receive any argument, since there's no reliable means of determining if the promise was fulfilled or rejected. This use case is for precisely when you do not care about the rejection reason, or the fulfillment value, and so there's no need to provide it. (mdn)
Instead, simply use .then:
const sql = require("mssql")
const config = require("../config")
router.get("/express-route", (req, res) => {
sql.connect(config.properties).then(pool => {
return pool.request()
.input('username', sql.NVarChar(32), req.params.username)
.execute('do_something_with_username')
.then(response => {res.send(response); return response;}) // pass this response
.catch(err => res.send(err))
.then(response => {
console.log('response', response) // to here
sql.close()
})
})
}
You can, in fact, simplify things by writing your code within an async function
const sql = require("mssql")
const config = require("../config")
router.get("/express-route", (req, res) => {
sql.connect(config.properties).then(async pool => {
try {
const response = await pool.request()
.input('username', sql.NVarChar(32), req.params.username)
.execute('do_something_with_username');
// do another request
const otherResponse = await pool.request() ... ;
res.send(response);
} catch (err) {
res.send(err);
} finally {
sql.close();
}
})
}
This lets you write code in a more linear manner.
Related
I have a problem don't know why i can't get return data from the function on another file, here what i try
my file.js
const psm = require("../services/psm");
psm.show(12).then((res) => console.log(res));
my service.js
const axios = require("../plugins/axios").default;
const module = "psm";
exports.show = async (payload) => {
await axios
.get(`/${module}/${payload}`)
.then((res) => {
return res.data.data;
})
.catch((err) => {
return Promise.reject(err.response);
})
.finally(() => {});
};
i get undefined return..
Problems in your code:
show function doesn't explicitly returns anything; as a result, promise returned by the show function is fulfilled with the value of undefined
Improvements that can be made in your code:
catch and finally blocks are not needed; catch block is unnecessary because rejected promise returned as a result of catch block will need to be handled by the code that calls the show function.
You will need the catch method or block in the calling code anyways. So, just remove the catch block and allow the calling code to catch and handle the error
show function doesn't needs to be async. You can just return the result of axios.get or axios.get(...).then(...)
Final version of "show" method:
exports.show = (payload) => {
return axios
.get(`/${module}/${payload}`)
.then((res) => {
return res.data.data;
});
}
You can call this function as:
psm.show(12)
.then(res => console.log(res))
.catch(error => { /* handle the error */ });
Alternate version of show function:
exports.show = (payload) => {
return axios.get(`/${module}/${payload}`);
}
You can call this version of show function as:
psm.show(12)
.then(res => console.log(res.data.data))
.catch(error => { /* handle the error */ });
I've trying to retrieve the data, but I can't return it, can only see it in the console,
it's a simple axios get function but for some reason, I keep getting Promise even after using async/await.
my goal is to save the data to the memory.
any help would really be appreciated
let fetchTodo = async () => {
await axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then(res => console.log(res.data))
.then(res => { return res })
.catch(err => console.log(err))
};
console.log("TEST: ", fetchTodo())
console
Asycn function always returns a promise, to get data from the fetchTodo function you need to create another async function which will await the result returned by fetchTodo(). if you are using react, you can use states and update the state while you are inside the .then chain of the fetchTodo function.
Asycn function always returns a promise. For getting or saving data you need to get it from .then() function. Here you can check the example. Hope so it will help you.
let fetchTodo = async () => {
await axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then(res => console.log(res.data))
.then(res => {
// here you can performance your task, save data, send
// response or anything else
return res
})
.catch(err => console.log(err))
};
fetchTodo()
The async/await syntax means a function will return a Promise.
If you want to return the value, you could do something like this:
let fetchTodo = async () => {
try {
const res = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
return res;
} catch (error) {
console.log(error);
}
};
// For the folowing code to work, it must be placed inside a async function as well
const res = await fetchTodo();
console.log(`Test: ${res.data}`);
// If it's a Top level call, use the folowing code
const res = fetchTodo().then( res => {
const data = res.data;
// The rest of your code goes here.
// ...
// ...
// ...
}).catch( error => {
console.log(error);
});
Some more information about it on: How can I use async/await at the top level?
The problem
I'm creating an express server which fetches currency exchange rates from an API. In the route I fetch those exchange rates via a helper function and I then want to return them in the response body on the format {data: rates, status: 200}.
However, the only thing returned from the route is {status: 200} as the exchange rates are undefined (pending promise). The fetch goes through successfully, i.e is not caught in the catch clause nor are the default results returned. They key 'rates' also exists.
I don't understand why this is undefined nor how to fix it as I am awaiting the response from the service before returning from the route. I've also tried encapsulating the router response in a .then clause instead of using await but I encounter the same problem.
API service fetch
require("isomorphic-fetch");
const { DEFAULT_RATES } = require("../resources/other/default_exchange_rates");
// Documentation: https://currencyfreaks.com/documentation.html
let domain = "https://api.currencyfreaks.com/";
/*
* Retrieve exchange rates from USD to other currencies.
* Return object format: {EUR: "2.0293", XXX: "0.55736", ...}
*/
exports.getExchangeRates = async () => {
return await (
fetch(`${domain}latest?apikey=${process.env.EXCHANGE_RATE_API_KEY}`)
.then((res) => {
if (res.status > 200) {
return DEFAULT_RATES;
}
let api_response = res.json();
return api_response.rates;
})
// Catch parse error
.catch((err) => {
console.log(err);
})
);
}
Route
const service = require("../services/currency_api");
const express = require("express");
const router = express.Router();
router.post("/", async (req, res) => {
try {
const rates = await service.getExchangeRates();
return res.status(200).send({ data: rates, status: 200 });
} catch (err) {
console.log(err);
return res.stats(400).send({ error: "An error occurred", status: 400 });
}
});
module.exports = router;
/*
Postman test response:
{
"status": 200
}
*/
Change callback containing:
let api_response = res.json();
To:
.then((res) => {
if (res.status > 200) {
return DEFAULT_RATES;
}
return res.json();
})
.then(api_response => api_response.rates);
The fetch response.json() method returns a promise, so to get the actual value you either have to await for it or return the promise and add another .then to wait for res.json() to resolve.
In turn, when you're not waiting for res.json() your promise resolves to undefined(api_response is a promise, and rates is undefined), and then data is also undefined
The working solution using baldrs answer
exports.getExchangeRates = () =>{
let url = `${domain}latest?apikey=${process.env.EXCHANGE_RATE_API_KEY}`;
return (
fetch(url)
.then((res) => {
if (res.status > 200) {
return DEFAULT_RATES;
}
return res.json();
})
.then((data) => data.rates)
.catch((err) => {
console.log(err);
})
);
}
I have 3 tables (services, practitioners, network) in my postgres database and I want them all to show in my API, but I got this error
(node:21300) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
and this is the only output I could get
json response
here is my code.
const handler = (req, res, db, tableName) => {
try{
db.select('*').from(tableName)
.then(data => {
if(data.length){
res.status(200).json({tableName: data});
}
})
}catch(err){
res.status(400).json(err)
}
}
const content = (req, res, db) => {
handler(req, res, db, 'services')
handler(req, res, db, 'practitioners')
}
module.exports = { content };
edit:
here's what I did from Nabil Farhan's answer, and it's working just what I wanted. screenCapture
const getData = async (db, tableName) => {
return new Promise((resolve, reject) => {
db.select('*').from(tableName)
.then(data => {
resolve({[tableName]:data})
})
});
}
const contentHandler = async (req, res, db) => {
// get the argument from get request
let allTable = [];
const table_a = await getData(db, 'services');
const table_b = await getData(db, 'practitioners');
allTable.push(table_a);
allTable.push(table_b);
res.status(200).json({data: allTable});
}
module.exports = { contentHandler };
I recommend you to use promise like this:
async function getData(tableName) {
return new Promise(function (resolve, reject) {
db.select("*")
.from(tableName)
.then((data) => {
resolve(data);
});
});
}
async function run(){
var allTable = [];
const firstTable = await getData('testingDB');
const secondTable = await getData('user');
allTable.push(firstTable);
allTable.push(secondTable);
res.status(200).json({data: allTable});
}
run().then(() => {
console.log("Finished!");
})
I see a couple potential issues here.
Unhandled Promise rejection:
Add a catch block after then (you can rethrow to put it in the existing catch block).
.then(data => {
if(data.length){
let responseData = {}
responseData[tableName] = data
res.status(200).json(responseData)
}
})
.catch(err) {throw err}
tableName is also not going to be interpreted as variable, but as a literal property name, so I changed it to get what I think you were going for.
For the header error, you are setting the response twice, once for "services", then again for "practitioners". One possible solution is to remove the res.status... line from handler and use Promise.all in content and moving the response setting there:
const content = (req, res, db) => {
Promise.all(
handler(req, res, db, 'services')
handler(req, res, db, 'practitioners')
)
.then(allData => {
//use reduce/Object.assign to combine the individual data objects
allData.reduce((finalResponseData, data) => {
if(!data.length) return finalResponseData
Object.assign(finalResponseData, data)
})
.then(finalResponseData => res.status(200).json(finalResponseData)
.catch(err) {res.status(400).json(err)}
}
I have a code below where in I want to finish doSomethingFirst() before proceeding with the rest of the code:
async doSomething() {
const response = await doSomethingFirst(); // get the response from this first
if(response) {
// rest of the code
}
}
async doSomethingFirst {
const response = await client
.query({
query,
fetchPolicy: "network-only",
variables: {
someVariable: value
}
})
.then(response => {
console.log(response);
})
.catch(err => {
// error
});
return await response;
}
However, the response in doSomething() comes back as undefined. What's wrong with this structure?
Give this a try, normally works for me, if not maybe the problem is elsewhere an it's not returning and actual data?
async doSomethingFirst {
const response = await client
.query({
query,
fetchPolicy: "network-only",
variables: {
someVariable: value
}
})
.then(response => { return response.json();})
.then(responseData => {console.log(responseData); return responseData;})
.catch(err => {
// error
});
}
You should return the response. Anyway, you can just do something like this:
doSomethingFirst() {
return client
.query({
query,
fetchPolicy: "network-only",
variables: {
someVariable: value
}
})
}
async doSomething() {
try {
const response = await doSomethingFirst();
if (response) {
// rest of the code
}
}
catch (err) {
console.log(err)
}
}
A few things you might want to know:
Inside doSomethingFirst you are using await and also chaining .then you don't have to do that because they're the same.
I made doSomethingFirst a non-async function because since doSomething is an async function you can just return the promise from doSomethingFirst and await the response inside doSomething also error handling can be done with the try-catch blocks as I did.