everyone! I have problem with async/await functions.
This is code from my backend. I try to save information of the person who just registered.
I really don't understand why Redirect()
function executes before functions with await
. All executes in async function. Main problem of this is empty "login","email" and user's profile picture sections on the profile page. Profile page gets login, email and profile from server with AJAX and when server redirects to this page nothing is loaded. But if I refresh profilePage, login, email and profile picture show up, what tells me that it is just haven't downloaded yet when redirection starts. It would be great if someone, who understand what is going on, will explain situation
app.post('/regPage.html', (req, res) => {
var form = new formidable.IncomingForm({
uploadDir: __dirname '\\uploads',
keepExtensions : true,
maxFileSize : 10*1024*1024,
multiples : true,
});
console.log(form);
form.parse(req, async function (err, fields, files) {
if(err) console.error(err);
let userData = fields;
console.log(fields);
console.log(files);
async function createUserFolder() {
fs.mkdir(path.join(__dirname, `/users/${fields.login}`),{ recursive: true }, err => {
if (err) throw err;
console.log('User folder created...');
return;
});
}
await createUserFolder();
console.log(typeof fields);
console.log('Right after consolelog files');
async function writingDataToFolders() {
fs.writeFile(path.join(__dirname, `/users/${fields.login}`, `${fields.login}.json`), JSON.stringify(userData),
err => {
if (err) throw err;
console.log("User file created...")
}
);
//if(files.profilePic.originalFilename.split('.').pop() == undefined) {
fs.rename(files.profilePic.filepath, path.join(__dirname, `/users/${fields.login}`, `${fields.login}_profilePic.${files.profilePic.originalFilename.split('.').pop()}`), function(err){
if(err) {
console.log(err);
fs.unlink(files.profilePic.filepath, err => {
if(err) throw err;
console.log('Rename error on no profile pic');
});
}
console.log("Successfully uploaded");
return;
});
//}
}
// Data entry in MySQL, cookie generating
let cookieId = uuid.v4();
console.log(cookieId);
async function writingDataToDatabase() {
let sql = 'SELECT cookieId FROM profiles WHERE cookieId= ?;';
let query = db.query(sql, cookieId, (err, results) => {
if(err) throw err;
console.log(results);
if(results == "") {
console.log('No such CookieId in database!...');
const profileObjForMysql = {
login : fields.login,
email : fields.email,
password : fields.password,
cookieId : cookieId
}
//setCookie('ID', cookieId, 365);
sql = `INSERT INTO profiles SET ?;`;
query = db.query(sql, profileObjForMysql, (err, result) => {
if(err) throw err;
console.log(result);
console.log('Profile added to MySQL...');
return;
});
}
});
}
async function createNewUserEndpoints() {
let newUserEndpont =`\n \n router.get(\'/${fields.login}/${fields.login}_profilePic.${files.profilePic.originalFilename.split('.').pop()}\', (req, res) => {
res.sendFile(path.join(__dirname, \"/${fields.login}/${fields.login}_profilePic.${files.profilePic.originalFilename.split('.').pop()}\"));
console.log(\'Hello\');
});
router.get(\'/${fields.login}/${fields.login}.json\', (req, res) => {
res.sendFile(path.join(__dirname, \'/${fields.login}/${fields.login}.json\'));
}); \n`;
fs.appendFile(path.join(__dirname, `/users/users_router.js`,), newUserEndpont ,(err) => {
if(err) throw err;
return;
});
console.log('New endpoint for user added...');
}
res.cookie('ID', cookieId, {httpOnly: false, maxAge : 999999999});
await writingDataToFolders();
console.log("Data was written to foldres...");
await writingDataToDatabase();
console.log("Data was written to Database...");
await createNewUserEndpoints();
console.log("New endpoint for user was created...");
res.redirect(301, '/profilePage.html');
});
});
I also tried contain all "await function_name" into function like this:
async function redirect() {
await writingDataToFolders();
console.log("Data was written to foldres...");
await writingDataToDatabase();
console.log("Data was written to Database...");
await createNewUserEndpoints();
console.log("New endpoint for user was created...");
res.redirect(301, '/profilePage.html');
}
redirect();
but it didn't work too
CodePudding user response:
Your async
functions are not really asynchronous, because you don't await the callback. One way to achieve this is to use util.promisify
, which converts the callback-flavored function into a function returning a promise, which you can await
:
async function createUserFolder() {
await util.promisify(fs.mkdir)(
path.join(__dirname, `/users/${fields.login}`),
{ recursive: true }
).then(() => {
console.log('User folder created...');
});
}
In other words: fs.mkdir
is a function that executes asynchronously and invokes a callback when done. util.promisify(fs.mkdir)
is a function that returns a promise, which resolves when the asynchronous execution is done.
By contrast, fs.mkdirSync
is a synchronous function which blocks the Node.js event loop. This should be avoided if you expect many parallel requests to your server.