Training on promise and await / async with fetch in another function - node.js

I go on with praticing in JS.
This time, I try to do quite the same thing using async / await or promise :
const url = 'https://jsonplaceholder.typicode.com/todos/1';
Async / await version :
async function getData() {
const response = await fetch(url);
const data = await response.json();
return data;
}
const callGetData = async () => {
try {
const data = await getData()
console.log(data);
} catch (error) {
console.log("Something gone wrong")
}
}
Promise version
function getData() {
return new Promise((resolve, reject) => {
fetch(url)
.then(res => res.json())
.then(data => resolve(data))
.catch(error => reject(error));
});
}
const callGetData = () => {
getData()
.then(data => console.log(data))
.catch(error => console.log("Something gone wrong"));
}
and finally :
callGetData();
Both snippets seem to work. It's easier to me to write the async / await version.
Questions :
do I use promise properly in this case ?
is there some possible improvements ?
Thank you for your help.

fectch is also a promise and you are trying to wrap a promise inside a new Promise
more on the Promise version you can simply return it from the function as
getData(url){
return fetch(url)
.then(response => response.json()).then(jsonResponse=>jsonResponse)
.catch(err=>err)
}
now getData returns a promise. we can simply do as :
getData().then(data=>console.log(data))

Related

Why am I getting an Unexpected token async on node.js?

Hi,
I have this code on my server file:
getName(){
const promise = new Promise((resolve, reject) => {
conn.query("SELECT name FROM members WHERE id=1", (err, res, fields) => {
if (err) reject(err);
resolve(res);
});
});
}
func() async {
try{
const data = await getName();
console.log(data);
} catch(e) {
console.log(e);
}
}
but I get this error: Unexpected token async so I removed async but then I get another error saying: Unexpected token {
What is happening here? I have node latest version: v10.24.1
Thank you.
The definition of your anonymous async function is wrong, try to change it like this example.
(async function() {
// Your code
})();
Also, you didn't return the promise from your getName() function.
getName() {
return new Promise((resolve, reject) => {
// Your code
})
}
More information about functions and async/await.
I think it is better if you use only async await and don't combine it with try and catch. That may give weird result. Try to refactor it only with async await syntax.
async func(){
const data = await getName();
console.log(data);
}

Handling nested promises

I am trying to reject a value inside a nested promise but it doesn't seem to actually reject it correctly. In the code below, when I get an error from promiseVariable, it doesn't reject with the error. In the promiseVariable.catch statement, I have reject(err). Shouldn't that reject with that error for the whole promise?
return new Promise((resolve, reject) => {
const user = anotherFunction();
if (!user) {
promiseVariable.then((data) => {
user = data;
}).catch((err) => {
reject(err)
})
}
resolve(user);
});
Because it will start the promiseVariable chain and jump over to resolve. In the .then, you should resolve there, or put an else.
return new Promise((resolve, reject) => {
const user = anotherFunction();
if (!user) {
promiseVariable
.then(resolve)
.catch(reject);
} else {
resolve(user);
}
});
It seems you're over-promising, if that's a word. You can just "await" for your other promise to complete.
Here, anotherFunction is a simulated Promise, where after 3 seconds it returns a valid object for your conditional if(!user).
You can try changing resolve({user: 1234}) with a false (or falsy) value to see its rejection.
function anotherFunction() {
return new Promise((resolve,reject) => {
setTimeout(() => resolve({user: 1234}), 3000)
});
}
async function mainFunction() {
const user = await anotherFunction();
return user || {error: 404};
}
mainFunction().then(result => console.log(result));

Program doesn't await async function before continuing flow

In the following code, the csv2pg function is async
const postUsages = async (req: MulterRequest, res: Response, next: any) => {
try {
const result = await csv2pg(req, next);
res.status(200).json({
msg: 'File uploaded/import successfully!',
file: req.file,
});
} catch (err) {
res.status(400).json({
msg: 'File uploaded/import failed!',
file: req.file,
});
}
};
The problem is, the await doesn't seem to await the function being finished before returning the res.status(200)
Here is the content of the csv2pg function that is being called (the async bit in this code is the forEach and the pool.query)
const csv2pg = (req: MulterRequest, next: any): any => {
let provider_id = req.body!.provider_id;
const filePath = appRoot + '/reports/' + req.file.filename;
const stream = fs.createReadStream(filePath);
const csvData: any[] = [];
const csvStream = csv
.parse()
.on('data', (data: any) => {
csvData.push(data);
})
.on('error', (err: any) => {
throw err.message;
})
.on('end', () => {
csvData.shift();
csvData.forEach((row) => {
pool.query(
`INSERT INTO usage (date_and_time, consumption, reading_quality, provider_id)
VALUES ((TO_TIMESTAMP($1, 'DD/MM/YYYY HH24:MI') AT TIME ZONE 'Australia/Melbourne')::TIMESTAMP WITH TIME ZONE, $2, $3, ${provider_id})`,
row,
(err: any) => {
if (err) {
next(new Error(err));
}
}
);
});
fs.unlinkSync(filePath);
});
stream.pipe(csvStream);
};
Another problem with this is that when there's an issue, there's another error message on top saying that the headers were already set (of course, the server already returned to the client by that time)
Ideally, when an error is raised, the whole function should stop, return the error message, and wait for new incoming requests
In order to be able to wait for csv2pg to finish all async operations, it must return a promise. Since the async actions are in a loop, we have to use Promise.all. Try this:
const csv2pg = (req: MulterRequest, next: any): any => {
return new Promise((resolve, reject) => {
let provider_id = req.body.provider_id;
const filePath = appRoot + "/reports/" + req.file.filename;
const stream = fs.createReadStream(filePath);
const csvData: any[] = [];
const csvStream = csv
.parse()
.on("data", (data: any) => {
csvData.push(data);
})
.on("error", (err: any) => {
reject(err.message);
})
.on("end", () => {
csvData.shift();
const promisesArray = csvData.map((row) => {
return new Promise((resolve, reject) =>
pool.query(
`INSERT INTO usage (date_and_time, consumption, reading_quality, provider_id)
VALUES ((TO_TIMESTAMP($1, 'DD/MM/YYYY HH24:MI') AT TIME ZONE 'Australia/Melbourne')::TIMESTAMP WITH TIME ZONE, $2, $3, ${provider_id})`,
row,
(err: any) => {
if (err) {
reject(new Error(err));
} else {
resolve();
}
}
)
);
});
Promise.all(promisesArray).then(() => {
fs.unlinkSync(filePath);
resolve();
})
});
stream.pipe(csvStream);
});
};
Please note, I also wrapped your pool.query in a promise, since this function doesn't return a promise by default.
The reason could be that you are using this code inside the for-loop. Using Promise.all would fix the problem. I would recommend this post to you: https://www.freecodecamp.org/news/promise-all-in-javascript-with-example-6c8c5aea3e32/.
It explains everything in detail.

Request promises with actions-on-google node v2

I have a similar problem like Use Async Functions in DialogFlow WebHook but that solution, changing request-promises for request-promises-native, didn't work for me, the difference it's that I'm using actions-on-google lib with ActionsSDK instead DialogFlow one, here is my code:
function call() {
var options = {
url: "https://google.es"
};
return request(options)
.then((res) => {
console.log("Success", res);
Promise.resolve();
})
.catch((err) => {
console.log("Error", err);
Promise.resolve();
});
}
const handleAction = (conv) => {
call()
.then(() => {
console.log("Going to ASK");
conv.ask('Hi, how is it going?');
return Promise.resolve();
})
.catch(error => {
console.log("Ask ERROR");
conv.ask('Hi, how is it going?');
return Promise.resolve();
});
}
app.intent('actions.intent.MAIN', (conv) => {
handleAction(conv);
});
If I change the call function for this one:
function call() {
let prom = new Promise((resolve,reject) =>{
resolve();
});
return prom;
}
It works like a charm. I don't understand where I'm wrong, I'm returning promises until the intent. Any idea?
Thanks!
you can resolve this problem using async/await. It will look like this. It might help you.
(async () => {
async function call() {
var options = {
url: "https://google.es"
};
return await new Promise((resolve, reject) => {
request(options)
.then((res) => {
resolve(res);
})
.catch((err) => {
console.log("Error", err);
reject(err)
});
}
}
const handleAction = await call(); //you will get result on handle Action varaible
})();

How to implement promise in nodejs?

How to implement promise in nodejs? could anyone provide some examples
for implementation of this?
Thanks in advance.
I agree with the comments on the original question. Docs explain very well. You can find more info here (includes sample)
Or look at the example below.
const asyncThingWithPromise = () => {
var promise = new Promise((resolve, reject) => {
try{
// do something async here. Like get data from a server or read a file from disk etc.
var value = 'My Async Data';
resolve(value) // handled by promise's then()
}catch(error){
reject(error) // handled by promise's catch()
}
});
return promise;
}
// usage with then/catch
asyncThingWithPromise()
.then(value => console.log(value))
.catch(error => console.error(error));
// usage with async / await
try{
const value = await asyncThingWithPromise();
console.log(value);
}catch(err){
console.error(err);
}

Resources