createFolder() function is returning an empty array. I am not sure what I am doing wrong but it needs to return the items within project_array
function get_project_folders(){
return new Promise((resolve, reject)=>{
fs.readdir(__dirname + '/projects', (error, data1)=>{
if(error){
reject(console.log(`Error. Unable to read directory - ${error}`))
}else{
resolve(data1)
}
})
})
}
async function createFolder(){
let list_of_projects = await get_project_folders()
let project_array = []
return new Promise((resolve, reject)=>{
for(let project of list_of_projects){
let splitProject = project.split("-")
fs.readdir(__dirname + `/projects/${splitProject[0]}-${splitProject[1]}`, (error, data1)=>{
if(error){
console.log('Error. Unable to read directory.')
}else{
project_array.push({circuit: splitProject[0], fuse: splitProject[1], pole: data1})
}
})
}
resolve(project_array)
})
}
async function testIt(){
let folderData = await createFolder()
console.log(folderData)
}
testIt()
This is a classic, what you are doing is resolving the promise with the empty array before your node fs async methods have resolved. Try this instead:
async function createFolder(){
const list_of_projects = await get_project_folders();
const result = await Promise.all( list_of_projects.map(project => new Promise((resolve, reject) => {
const splitProject = project.split("-");
fs.readdir(__dirname + `/projects/${splitProject[0]}-${splitProject[1]}`, (error, data1) => {
if(error){
console.error('Error. Unable to read directory.');
resolve( null );
} else {
resolve({
circuit: splitProject[0],
fuse: splitProject[1],
pole: data1
});
}
});
});
// Filter out the errors that resolved as `null`
return result.filter( Boolean );
}
In essence, wrap every fs. call in a promise, then use Promise.all to generate an array of promises. Because Promise.all requires all to be resolved for it to be resolved, make sure you even resolve when there is an error - just return something falsy (in my case null) so you can filter it out later.
Related
Is this possible way to return resolve or reject message from one function to another?
As I am writing to pass resolve message in postman whenever my task is completed or reject message when there is some error
But after after writing return it still not returning the resolve message or reject message inside Postman
any idea how this can be resolve?
async function readFile(filePath) {}
async function getAllFile(filePath) {
const paths = await readFile(filePath);
}
async function filterFiles(filePath) {
const paths = await getAllFile(filePath);
}
function addDocument(childProduct){
return new Promise((resolve, reject) => {
Document.create({
name: childProduct,
},
}).then(function (filePath) {
filterFiles(filePath);
let msg = "Document created Succesfully";
return resolve(msg);
})
.catch(function (err) {
return reject("Can't be updated please try again :) " + err);
});
});
}
function updateDoc(data){
return new Promise((resolve, reject) => {
Document.update({
name: data.name,
}
where: {
product_id: data,
},
})
}).then(function (childProduct) {
addDocument(childProduct);
let msg = "Updated Successfully";
return resolve(msg);
})
.catch(function (err) {
return reject("Can't be updated please try again :) " + err);
});
}
Product.findOne and Document.findAll return a Promise, so they can be returned and awaited directly.
You can chain await func1(); await func2(); await func3() in one try{} block, and catch any error that happens in one place :
const filterFiles = async filePath => {
const paths = await getAllFiles(filePath);
// .. Do something else here
return paths // This is a Promise because async functions always return a Promise
}
const findOneDoc = name => Product.findOne({ where: { name } }); // This func returns a Promise
const findAllDocs = product_id => Document.findAll({ // This func returns a Promise too
raw: true,
where: { product_id }
});
(async () => {
try {
const childProduct = await findOneDoc("some_name");
console.log("All good until now!");
const filePath = await findAllDocs(childProduct._id);
console.log("Still good");
const filteredFiles = await filterFiles(filePath);
console.log("All went well.");
console.log(filteredFiles);
} catch (err) {
// If any of the functions above fails, the try{} block will break and the error will be caught here.
console.log(`Error!`, err);
}
})();
There are few things I would like to mention.
When you create a promise, it should have resolve() and reject() inside it.
for ex-
function testPromise() {
return new Promise((resolve, reject) => {
// your logic
// The followin if-else is not nessesary, its just for an illustration
if (Success condition met) {
resolve(object you want to return);
}else {
reject(error);
// you can add error message in this error as well
}
});
}
// Calling the method with await
let obj = await testPromise()
// OR call with then, but its better to go with await
testPromise().then((obj)=>{
// Access obj here
})
In the method which you have written, You have applied .then() method to non promise object. You have to complete the promise block first with resolve() and reject() inside it. Then you can return that promise from a function, use it in async function Or apply .then() block on it.
Also you don't need to add return statement to resolve() and reject() statement. The system will take care of it.
You can also use try catch block inside a promise. Its better to write reject() statement in catch block, if anything goes wrong.
I'm trying to use apolloFetch inside a Promise.all in my Node.js microservice but keep getting an error that the query is empty. The reason for using apolloFetch is to call another micro service and pass it an array of queries. Can someone give me some direction? My code is as follows:
const uri = "dsc.xxx.yyyy.com/abc/def/graphql";
const apolloFetch = CreateApolloFetch({uri});
const QryAllBooks = {
type: new GraphQLList(BookType),
args: {},
resolve() {
return new Promise((resolve, reject) => {
let sql = singleLineString`
select distinct t.bookid,t.bookname,t.country
from books_tbl t
where t.ship_status = 'Not Shipped'
`;
pool.query(sql, (err, results) => {
if (err) {
reject(err);
}
resolve(results);
const str = JSON.stringify(results);
const json = JSON.parse(str);
const promises = [];
for (let p = 0; p < results.length; p++) {
const book_id = json[p].bookid;
const query = `mutation updateShipping
{updateShipping
(id: ${book_id}, input:{
status: "Shipped"
})
{ bookid
bookname }}`;
promises.push(query);
}
//Below is the Promise.all function with the
//apolloFetch that calls another graphql endpoint
//an array of queries
Promise.all(promises.map(p => apolloFetch({p}))).then((result) => {
//this is the problem code^^^^^^^^^^^^^^^^^^^^^
resolve();
console.log("success!");
}).catch((e) => {
FunctionLogError(29, "Error", e);
});
});
});
}
};
module.exports = {
QryAllBooks,
BookType
};
It looks like apolloFetch requires query - you are passing p
change
Promise.all( promises.map(p=>apolloFetch({p})) )
to
Promise.all( promises.map(query=>apolloFetch({query})) )
You also call resolve twice
To resolve all errors or success
const final_results = []
Promise.all(promises.map(query => apolloFetch({
query,
}))).then((result) => {
final_results.push(result)
}).catch((e) => {
final_results.push(e)
}).then(() => {
resolve(final_results)
});
You immediately resolve or rejects once the pool.query() callback starts:
if(err){ reject(err);}resolve(results);
So unless the query fails, you never resolve with the results from the apolloFetch calls, since the promise is already resolved with the pool.query() results. I guess you're missing an else block:
if( err ) {
reject();
}
else {
const promises = ...
}
PS: you can try using node.js' util.promisify() to turn pool.query() into a promise as well so you can just write something resembling: query(...).then(results=>results.map(apolloFetch) instead of ahving to mix callbacks and promises.
I can't seem to find a relevant solution to this issue.
I am trying to use a foreach loop to call out for data. I have tried multiple variations of packaging this in promises but cannot seem to halt this function from proceeding before finishing the loop. Hoping someone may have some insight.
async function getData(){
temparray [] = { data to iterate over };
await getAgents();
console.log('done');
function getAgents(){
return new Promise(resolve => {
temparray.forEach((deal) => {
pipedrive.Persons.get(deal.agent, function(err, person) {
if (err) throw err;
console.log("trying to get agent " + deal.agent)
console.log(person.name);
});
});
}); // end of promise
};
};
So what I'm trying to do here is create a promise that resolves once all of the async calls are completed, but the process marches on before this has completed. Hence 'done' logs to the console before the getAgents() function has completed and logged the names. I suspect it has to do with the callbacks, but I've tried converting it to a promise, I've tried util.promiseify, and I've looked at building an array of promises and then using promise.all but haven't tested it.
Here's how you should do with another example
exec = async () => {
let tmp = [1,2,3,4,5,6];
let value = await Promise.all(tmp.map(id => getIdAfterTimeout(id)));
console.log(value);
}
getIdAfterTimeout = (id) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
return resolve(id);
}, 2000);
})
}
exec();
You could covert a function with callback style to a promise.
My example for you case:
async function getData() {
temparray[] = {data to iterate over};
let persons = await getAgents(temparray);
console.log(persons);
console.log('done');
};
async function getAgents(temparray) {
await Promise.all(
temparray.map((deal) => {
return new Promise(resolve => {
pipedrive.Persons.get(deal.agent, function(err, person) {
if (err) throw err;
console.log("trying to get agent " + deal.agent)
console.log(person.name);
resolve(person);
});
})
})
);
};
You can use Promise.all or old school for loop (fori), I think you need read more about Promise async/await.
async function getData(){
// this or you can do await
Promise.all(temparray.map(temp => getAgents(temp)))
.then(data => {
console.log('done');
})
.catch(e => {
console.log('error' );
})
// if you do await .. do like this
const {error, data } = await Promise.all(promises);
console.log(data);
}
function getAgents(id){
return new Promise((resolve, reject) => {
pipedrive.Persons.get(deal.agent, function(err, person){
if (err)
return resolve({error: err, data: null});
return resolve({error : null, data: person});
});
}); // end of promise
}
I even was stuck in similar problem yesterday. I applied following logic to solve this
Create a counter that tracks how many async requests are completed
Increment the counter in the callback function of async request
Add check if counter is equal to length of array
Resolve the promise once the counter is equal to the length of input array
const fs = require('fs');
async function getData() {
const array = [1, 2, 3, 4, 5, 6];
// Create a counter that tracks how many async requests are completed
let counter = 0;
await getAgents();
console.log('done');
async function getAgents() {
return new Promise(resolve => {
array.forEach((item, i) => {
//do async stuff here
fs.writeFile(`${i}.file.txt`, `line in file ${i}`, err => {
if (err) throw err;
// Increment the counter in the callback function of async request
// Add check if counter is equal to length of array
if (++counter == array.length) {
// Resolve the promise once the counter is equal to the length of input array
resolve(counter);
}
});
});
});
}
}
getData();
Im trying to use async await on a function that returns a promise but the out put im getting is Promise { <pending> }. In here im using function called convertFiletoPDF which returns a promise. I need to get the output (the path that i have mention in resolve() ).
When i use it as
convertFiletoPDF(file).then((result) => {
console.log(result);
}).catch((err)=>{
console.log(err);
});
it gives the expected result.Whats wrong with the code below? im quite new to these async await and promises.
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
unoconv.convert(file, "pdf", function(
err,
result
) {
if (err) {
reject(err);
}
let File = file.substring(file.lastIndexOf("/")+1,file.lastIndexOf("."));
// result is returned as a Buffer
fs.writeFile(__dirname+"/files/converted/"+File+".pdf", result, error => {
/* handle error */
if (err) reject(error);
else resolve("./files/converted/"+File+".pdf");
});
});
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
let res = myfunc(file);
console.log(res);
The return value of an async function is a promise, so naturally that's what your console.log outputs. You need to either consume the result via await (within another async function) or use then/catch (within another async function).
This is what you're currently doing:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
let res = myfunc("some file");
console.log(res);
You need to be doing either this:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
(async() => {
try {
let res = await myfunc("some file");
console.log(res);
} catch (e) {
// Deal with the fact there was an error
}
})();
or with then and catch:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
myfunc("some file")
.then(res => {
console.log(res);
})
.catch(e => {
// Deal with the fact there was an error
});
convertFiletoPDF()
This function run and returned a Promise. This is fine.
myfunc()
Lets say myfunc takes 10 seconds. Javascript starts to wait newly created thread result from libuv via event loop mechanism. So, Javascript says, "That one is async, I will not wait, when it finishes it will let me know and i will run my then callback and then I will proceed with its output."
Javascript keeps his promise. Tries to run next below lines. myFunch is still working. Output is not ready yet. Returns undefined.
let res = myfunc(file);
console.log(res);
You get undefined.
Someone might find this example from my code useful. You can wrap it in a promise and then resolve the custom promise and then call another promise to confirm the receipt of the original web3 call.
return new Promise((resolve, reject) => {
tokenContract.methods.approve(
exchangeAddress,
BIG_NUMBER_1e50
)
.send({ from })
.once('transactionHash')
.once('receipt', receipt => resolve(receipt))
.on('confirmation')
.on('error', err => reject(err))
.then( receipt => // will be fired once the receipt its mined
console.log(receipt),
);
});
Im trying to use async await on a function that returns a promise but the out put im getting is Promise { <pending> }. In here im using function called convertFiletoPDF which returns a promise. I need to get the output (the path that i have mention in resolve() ).
When i use it as
convertFiletoPDF(file).then((result) => {
console.log(result);
}).catch((err)=>{
console.log(err);
});
it gives the expected result.Whats wrong with the code below? im quite new to these async await and promises.
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
unoconv.convert(file, "pdf", function(
err,
result
) {
if (err) {
reject(err);
}
let File = file.substring(file.lastIndexOf("/")+1,file.lastIndexOf("."));
// result is returned as a Buffer
fs.writeFile(__dirname+"/files/converted/"+File+".pdf", result, error => {
/* handle error */
if (err) reject(error);
else resolve("./files/converted/"+File+".pdf");
});
});
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
let res = myfunc(file);
console.log(res);
The return value of an async function is a promise, so naturally that's what your console.log outputs. You need to either consume the result via await (within another async function) or use then/catch (within another async function).
This is what you're currently doing:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
let res = myfunc("some file");
console.log(res);
You need to be doing either this:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
(async() => {
try {
let res = await myfunc("some file");
console.log(res);
} catch (e) {
// Deal with the fact there was an error
}
})();
or with then and catch:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
myfunc("some file")
.then(res => {
console.log(res);
})
.catch(e => {
// Deal with the fact there was an error
});
convertFiletoPDF()
This function run and returned a Promise. This is fine.
myfunc()
Lets say myfunc takes 10 seconds. Javascript starts to wait newly created thread result from libuv via event loop mechanism. So, Javascript says, "That one is async, I will not wait, when it finishes it will let me know and i will run my then callback and then I will proceed with its output."
Javascript keeps his promise. Tries to run next below lines. myFunch is still working. Output is not ready yet. Returns undefined.
let res = myfunc(file);
console.log(res);
You get undefined.
Someone might find this example from my code useful. You can wrap it in a promise and then resolve the custom promise and then call another promise to confirm the receipt of the original web3 call.
return new Promise((resolve, reject) => {
tokenContract.methods.approve(
exchangeAddress,
BIG_NUMBER_1e50
)
.send({ from })
.once('transactionHash')
.once('receipt', receipt => resolve(receipt))
.on('confirmation')
.on('error', err => reject(err))
.then( receipt => // will be fired once the receipt its mined
console.log(receipt),
);
});