calling two async functions one after another in .post function Node.JS - javascript

I want to receive an image from a client, convert it into text and then delete the image once it's converted. I'm using the following code:
app.post('/upload', (req,res)=>{
const myFile = req.files.file;
myFile.mv(`D:/web_projects/react-express-mongodb-template/server/pictures/${myFile.name}`)
let img = `D:/web_projects/react-express-mongodb-template/server/pictures/${myFile.name}`
convert(img);
remove(img)
})
app.listen(5000, () => {
console.log('server is running at port 5000');
})
async function convert(img){
const worker = createWorker();
console.log(worker)
await worker.load();
await worker.loadLanguage('eng');
await worker.initialize('eng');
const { data: { text } } = await worker.recognize(img);
console.log(text);
await worker.terminate();
}
async function remove(path){
try {
fs.unlink(path)
} catch(err) {
console.error(err)
}
}
So in the post method I call the convert function and then remove but remove gets executed first and so convert function results in error. Is there a way to handle this issue?

As convert is an async function, and thus returns a promise, replace:
convert(img);
remove(img)
With:
convert(img).then(() => remove(img));
However, this assumes that all awaited worker method calls in convert return promises. If this is not the case, and they run asynchronous code, then actually convert will not properly await those, and you should first promisify them.

Related

Converting a synchronous function to be async

As I was implementing service worker subscriptions, I noticed a message from Visual Studio Code, that the following function can be converted to be an async function:
Here is the my original synchronous code.
/**
* Returns the subscription if it is present, or nothing
*/
function getUserSubscription() {
return navigator.serviceWorker.ready
.then(function (serviceWorker) {
return serviceWorker.pushManager.getSubscription();
})
.then(function (pushSubscription) {
return pushSubscription;
});
}
I'm not sure how I'd convert this to be an async function. I thought I understood the gist of it, as in converting something like this:
fetchData()
.then(process())
.then(processAgain());
to this:
const response1 = await fetchData();
const response2 = await process(response1);
const response = await processAgain(response2);
But I've had no luck converting my function using this technique.
Use the async keyword in front of the function. Then await each Promise and return the result.
async function getUserSubscription() {
const serviceWorker = await navigator.serviceWorker.ready;
const pushSubscription = await serviceWorker.pushManager.getSubscription();
return pushSubscription;
}

Asynchronous function call from synchronous function (Node.js)

I am having trouble with getting access to a response from my asynchronous function. I understand this is a common issue, but I cannot find another question that pertains to my issue.
My Synchronous Function:
const output = getSeasons.getSeasons('*URL*', (data)=>{
return data
})
console.log(data)
My Asynchronous Function:
const getSeasons = async (url, callback) => {
seasonTitle = *ASYNCHRONOUS CALL THAT RETURNS AN ARRAY*
await seasonTitle
callback(seasonTitle)
}
My issue is that I want to be able to continue in my synchronous function utilizing "output" in future lines. The only solution I can think of is:
const output = getSeasons.getSeasons('*URL*', (data)=>{
return data
}).then(()=>{ console.log(data) }
My issue with this option is that all of my future code for this function will have to be written inside the ".then" function. I would much prefer to wait for a response before continuing on in my synchronous function without putting everything in ".then". Mainly because I will have multiple functions calling asynchronous functions and that will result in multiple nested ".then" functions.
EDIT:
Here is the actual code, the asynchronous call is scraping for elements with a class of seasons and then I am trying to return the array:
const output = getSeasons.getSeasons('https://www.rocketleagueesports.com/schedule/', (data)=>{
console.log(data)
})
console.log(output)
const getSeasons = async (url, callback) => {
const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()
await page.goto(url)
await page.waitForSelector('.match') //Waits for elements with class "match" to load before executing further
const seasonTitle = page.evaluate(() => {
const seasonTitleArray = Array.from(document.querySelectorAll('.sub-header .scoreboard-container .container-lg .show-on-md .select-options-container .seasons li'))
return seasonTitleArray.map(li => li.textContent)
})
await seasonTitle
callback(seasonTitle)
}
Why not use the await as you have done in getSeasons
const getSeasons = async funciton(url) {
return await *ASYNCHRONOUS CALL THAT RETURNS AN ARRAY*
}
(async () => {
const output = await getSeasons.getSeasons('*URL*')
console.log(output)
})()
async/await
If you don't want to write code in then block, then use async/await
async someFunction() {
const output = await getSeasons.getSeasons(...)
}
Besides that, your getSessions need some improvements. Why do you need both callback and async which return a Promise?
Try to refactor something like this:
const getSeasons = async function(url) {
return *ASYNCHRONOUS CALL THAT RETURNS AN ARRAY*
}

can await/async makes blocking to non-blocking process in javascript

I read this article from node
https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/
It says the code below is a process blocker:
const fs = require('fs');
const data = fs.readFileSync('/file.md'); // blocks here until file is read
console.log(data);
// moreWork(); will run after console.log
what if I add await?
will the code above becomes non-blocking or it will stay in its true nature?
Example code:
const fs = require('fs');
const data = await fs.readFileSync('/file.md'); // no more blocking
console.log(data);
Thank you
No, the code can't run since await must use in async function.
And await should use for function that return promise.
the code means:
// await new Promise(...)
// console.log(...)
new Promise().then((...) => console.log(...))
If you should non-block function, you should use fs.readFile instead.
Blocking means that the whole application is blocked.
So, all SetInterval, Promise, Events or whatever async callback are paused until that sync function ends its execution.
It's the same of what you get when you use a for..loop.
NodeJS provides you some non-blocking file system methods with callbacks, just change your code like this.
const fs = require('fs');
fs.readFile('/file.md', (err, data) => {
if (err) throw err;
console.log(data)
});
There is the only way.
await operator wait a promise, and wrapped in async function
you should code like this
const fs = require("fs");
function readFile(fileName) {
return new Promise((resolve, reject) => {
fs.readFile(fileName, (err, data) => {
if (err) reject(err);
resolve(data);
});
});
}
async function f1() {
try {
var x = await readFile("foo.json");
console.log(x);
} catch (e) {
console.log(e); // 30
}
}
f1();

When using async await, how do you specify a callback?

I was looking at how to use transactions in:
https://node-postgres.com/features/transactions
But in the following code example:
const { Pool } = require('pg')
const pool = new Pool()
(async () => {
// note: we don't try/catch this because if connecting throws an exception
// we don't need to dispose of the client (it will be undefined)
const client = await pool.connect()
try {
await client.query('BEGIN')
const { rows } = await client.query('INSERT INTO users(name) VALUES($1) RETURNING id', ['brianc'])
const insertPhotoText = 'INSERT INTO photos(user_id, photo_url) VALUES ($1, $2)'
const insertPhotoValues = [res.rows[0].id, 's3.bucket.foo']
await client.query(insertPhotoText, insertPhotoValues)
await client.query('COMMIT')
} catch (e) {
await client.query('ROLLBACK')
throw e
} finally {
client.release()
}
})().catch(e => console.error(e.stack))
It seems that the function will execute immediately. Also there doesn't seem to be a way to specify a callback. Would it make sense to place the entire block from "(async()...." into a function, and then in the final statement before the end of the try block, add :
await callbackfunction();
Does that make sense? What would be a better way to add a callback function ?
The point of await is that you don't use a callback. It returns the result of resolving the promise.
Without await:
do_something_asyc.then(function (data) { alert(data); });
With await:
var data = await do_something_asyc();
alert(data);

async/ await not waiting for async.map call to be completed

In my Node.js app I'm trying to use a helper function to gather and format some data to ultimately be returned via an API endpoint. I need to loop through an array, and for each entry, make an asynchronous call to my database. However, I'm unable to return this new array of data in my route once I map over it. I believe that this has something to do with the nature of 'async.map' but have been unable to figure it out from the docs. Am I missing something? Better way to do this?
router.get('/route',async (req,res) => {
const formattedData = await module.formatData(data);
// formattedData IS RETURNED AS UNDEFINED HERE
res.json({data:formattedData});
};
Relevant helper functions:
formatData: async(data) => {
// gets entire object from the id that I originally had
getNewData: (dataID) => {
const data = Data.find({_id:dataID},(error,response)=>{
return response;
})
return data;
},
const formatDataHelper = async(data,done) =>{
// THIS function queries database (reason I have to use async)
const newData = await getNewData(data);
done(null, newData);
}
function dataMap(data, callback) {
async.map(data, formatDataHelper, callback);
}
const returnData = await dataMap(data,(err,response)=>{
return response;
})
return returnData;
},
await only awaits something when you await a function that returns a promise that is linked to whatever you want to await. Your dataMap() function returns nothing, therefore await on that function doesn't await anything.
So, in order to work with await, your dataMap() function needs to return a promise that is tied to the asynchronous operation it is doing.

Categories

Resources