Im using Async on getJsonProducts, and I'm awaiting before console.log(products) but it still prints undefined. I thought await, pauses until the promise has been resolved?
Why aren't the products visible?
async function getJsonProducts(){
let products;
await fs.readFile('./products.json','utf-8',async (err,data)=>{
if(err)
throw err;
let r = /\"\_id.*\,(?=\"info\")|(?<=hex.*\})\,\"\_+v.*\d/g
let d = await data.replace(r,'');
d = await d.split('\n');d.pop();
products = await d.map(s=>JSON.parse(s));
//console.log(products) prints here
})
await console.log(products); //prints undefined here?
}
const seedProducts = async () => {
await getJsonProducts();
}
seedProducts();
I know there's other ways to implement this but I want to understand why this isn't working.
absolutely you will get undefined because you combined between async-await and the callback, also this is not how async-await works,
if you want to use async await , you can follow my code
async function getJsonProducts() {
return new Promise((reoslve, reject) => {
fs.readFile('./products.json', 'utf-8', async (err, data) => {
if (err) reject(err)
let r = /\"\_id.*\,(?=\"info\")|(?<=hex.*\})\,\"\_+v.*\d/g
let d = data.replace(r, '');
d = d.split('\n');
d.pop();
const products = d.map(s => JSON.parse(s));
resolve(products)
})
})
}
const seedProducts = async () => {
const products = await getJsonProducts();
conosle.log(products); // you will get products
}
seedProducts();
function getFile(cb) {
fs.readFile('./products.json', 'utf-8', (err, data) => {
if (err)
throw err;
let r = /\"\_id.*\,(?=\"info\")|(?<=hex.*\})\,\"\_+v.*\d/g
let d = data.replace(r, '');
d = d.split('\n');
d.pop();
cb(d.map(s => JSON.parse(s)));
})
}
async function getJsonProducts() {
this.getFile(products => console.log(products));
}
const seedProducts = async () => {
await getJsonProducts();
}
seedProducts();
Related
I have 2 files index.js and models.js
my index.js file requires the model.js file
const models = require("./modules/models.js");
app.post('/message', (req, res) => {
const _lead = models.createLead(req.body)
_lead.then(l => {
console.log("resulted in lead", JSON.stringify(l))
// GETTING UNDEFINED HERE
})
// const _message = await models.createMessage(req.body.message)
res.send();
});
My models.js file has a functions that contain Promises
const createLead = async function (payload) {
// Find lead
let result
new Promise((resolve, reject) => {
findLeadById(payload.lead.rid).then(async _lead => {
// If a lead has not been found
if (!_lead) {
if(payload.companyRid != payload.lead.rid){
await db.collection('leads').add(payload.lead).then((l) => {
result = payload.lead
result['id'] = l.id
})
}
} else {
result = _lead
}
}).then(() => {
console.log(" result of create lead ",JSON.stringify(result))
resolve(result)
}).catch(error => {
error.log("reject", error)
reject(error)
})
})
}
const findLeadById = async function (lead) {
new Promise(async (resolve, reject) => {
const ref = db.collection('leads');
console.log("finding lead", JSON.stringify(lead))
await ref.where("rid", "==", lead).get().then((s) => {
let obj = null
if(s){
s.forEach(doc => {
console.log("found the lead in loop", JSON.stringify(doc.data()))
obj = doc.data()
obj['id'] = doc.id
})
}
resolve(obj)
}).catch(error => {
error.log("reject", error)
reject(error)
})
})
}
exports.createLead = createLead;
exports.findLeadById = findLeadById;
The model.js returns an object as expected
console.log(" result of create lead ",JSON.stringify(result))
However, I'm expecting to see that same object in the index.js in the then block but I'm getting undefined.
console.log("resulted in lead", JSON.stringify(l))
// GETTING UNDEFINED HERE
The following is not waiting for the associated functions to finish
const _lead = models.createLead(req.body)
I have also tried adding async and await which also didn't work
const _lead = await models.createLead(req.body).then(res => {console.log("result", res) // Still undefined
})
I think you can use resolve for any success response, and reject for error response. Ex:
await db.collection('leads').add(payload.lead).then((l) => {
let result = payload.lead
result['id'] = l.id
resolve(result)
})
I'm not capturing the connect function to return in the getAllowedEmails function, when I do console.log in allowedEmails, it returns the emails correctly, but when I assign to the variable emails, it is returning empty. I think it's an async await problem but can't figured out.
static async getAllowedEmails() {
var MongoClient = require("mongodb").MongoClient;
//db url
let emails = [];
await MongoClient.connect(url, async function (err, client) {
const db = client.db("data-admin");
var myPromise = () => {
return new Promise((resolve, reject) => {
db.collection("users")
.find({})
.toArray(function (err, data) {
err ? reject(err) : resolve(data);
});
});
};
var result = await myPromise();
client.close();
let allowedEmails = [];
result.map((email) => allowedEmails.push(email.email));
console.log(allowedEmails)
emails = allowedEmails;
});
console.log(emails)
return emails;
}
Your code has couple of issues, I have fixed few and enhanced it, given below is the basic code, try to test it and if everything works then enhance it as needed:
const MongoClient = require("mongodb").MongoClient;
async function getAllowedEmails() {
let client;
try {
const allowedEmails = [];
client = await MongoClient.connect(url);
const db = client.db("data-admin");
const result = await db.collection("users").find({}).toArray();
result.map((email) => allowedEmails.push(email.email));
console.log(allowedEmails)
client.close();
return allowedEmails;
} catch (error) {
(client) && client.close();
console.log(error)
throw error;
}
}
const request = require('request-promise')
required this module and use it in this way the data and subData is options that i defined later...
const foo= (data, subData) => {
return request(data)
.then(result => {
console.log('result:',result)
return request(subData)
})
}
the problem is the request(data) result is not return but the request(subData) result is return
Q.allSettled([
foo(),
fo(),
f(),
.
.
.
])
and with q module create an array of promises, but i still cant get my expected return result
You can use any of the following methods to chain your promises and return both responses into an array
const foo = (data, subData) => {
let result;
return request(data)
.then(res => {
result = res;
return request(subData)
}).then(res => {
return [result, res]
});
}
//OR
const foo2 = (data, subData) => {
return request(data)
.then(res1 => {
return request(subData).then(res2 => {
return [res1, res2]
})
});
}
//OR
const foo3 = async (data, subData) => {
let res1 = await request(data);
let res2 = await request(subData);
return [res1, re2];
}
I would suggest the following approach instead of Promise Chaining or Q:
const fetchData = (data, subData) => {
const result = await request(data);
const resultSub = await request(subData);
console.log(result, resultSub);
};
I have the following code:
async function goodUsers(users) {
const filteredUsers = [];
users.forEach(async (userInstance) => {
console.log('TEST1');
const fromUserContacts = await db.userContactInvite.findAll({
where: {
fromUserId: userInstance.id,
},
});
console.log('TEST2');
await fromUserContacts.forEach((fromUserContact) => {
console.log('TEST3');
const userJson = fromUserContact.toJSON();
userJson.contactState = 'INVITATION_SENT';
filteredUsers.push(userJson);
});
console.log('TEST4');
});
console.log('FILTERED', filteredUsers);
return filteredUsers;
}
When I call goodUsers I get the following output:
TEST1
FILTERED
TEST2
TEST3
TEST4
FILTERED should be last (obviously).
I tried various options but I seem to be not understanding something here. Do you guys notice what's going on?
This's a correct behavior, async/await only affect the function where they are used. So you need to replace forEach which calls callback for each element, to for operator:
async function goodUsers(users) {
const filteredUsers = [];
for(user in users) {
console.log('TEST1');
const fromUserContacts = await new Promise(resolve => setTimeout(() => resolve(['c1', 'c2']), 500));
console.log('TEST2');
fromUserContacts.forEach(fromUserContact => {
console.log('TEST3');
filteredUsers.push('json');
});
console.log('TEST4');
}
console.log('FILTERED', filteredUsers);
return filteredUsers;
}
goodUsers(['u1', 'u2']);
Trying to get the variable random_song from the function functions.random_song
Function:
functions.random_song = () => {
fs.readFile('auto_playlist.txt', 'utf8', function(err, data) {
if (err) {
console.log(`${`ERR`.red} || ${`Error fetching song from auto playlist ${err}`.red}`);
}
let songs = data.split('\n');
songs.splice(-1, 1);
var random = Math.floor(Math.random()*songs.length);
let random_song = (songs[random]);
return random_song;
})
}
Attempting to callback the random song
functions.random_song(song => {
console.log(song)
})
The code just return undefined Ideas?
Your function:
functions.random_song = (callback) => {
fs.readFile('auto_playlist.txt', 'utf8', function(err, data) {
if (err) {
// Do stuff
return callback(err);
}
// Do stuff
callback(null, random_song);
})
}
And then call it:
functions.random_song((err, song) => {
// Do stuff
});
You may want to read more about using Promise/async-await instead of callback.
functions.random_song = () => {
let data = fs.readFileSync('auto_playlist.txt', 'utf8');
let songs = data.split('\n');
songs.splice(-1, 1);
var random = Math.floor(Math.random()*songs.length);
let rand_song = (songs[random]);
return rand_song;
}
console.log(functions.random_song())
got it working, thanks for the help <3
Following is the code which use Promise to handle file read and data processing task asynchronously
const fs = require('fs')
const functions = {}
functions.random_song = () => {
return new Promise((resolve, reject) => {
fs.readFile('auto_playlist.txt', 'utf8', function(err, data) {
if (err) {
console.log(err)
reject(err)
}
let songs = data.split('\n');
songs.splice(-1, 1);
var random = Math.floor(Math.random()*songs.length);
let random_song = (songs[random]);
resolve(random_song);
})
})
}
functions.random_song()
.then(song => console.log('Song Name', song))
.catch(err => console.error('Error fetching songs', err))
console.log('It will be executed before promise is resolved')
fs.readFile is asynchronus and your function will return before the file is read. Use fs.readFileSync instead. Like this:
functions.random_song = () => {
const data = fs.readFileSync('auto_playlist.txt', 'utf8');
let songs = data.split('\n');
songs.splice(-1, 1);
var random = Math.floor(Math.random()*songs.length);
let random_song = (songs[random]);
return random_song;
}