I'm trying to programmatically get an array of all of the PM2 process IDs in cluster mode.
const pm2 = require("pm2");
let allPids;
async function getPids() {
return await new Promise(resolve => {
pm2.list((err, list) => {
if (err) {
console.error(err);
} else {
resolve(list.map(process => process.pid));
}
});
});
}
getPids().then(pids => {
console.log(pids); // outputs an array of PIDs
allPids = pids;
});
console.log(allPids); // outputs undefined
The above code successfully gets all of the PIDs with pm2.list(), but I'm unable to access them outside of the .then() callback.
const pm2 = require("pm2")
let pids;
pm2.list((err, list) => {
if (err) {
console.log(err);
} else {
pids = list.map(process => process.pid);
};
});
console.log(pids); // outputs undefined
setTimeout(() => {
console.log(pids); // outputs array of PIDs
}, 1000);
This code also worked, but only in the setTimeout() callback.
The PM2 documentation was no help whatsoever.
Is there a way access the PIDs without placing all of my code in the .then()/setTimeout() callback? Or, is there a better solution?
Your function is async, so why not await?
const pm2 = require("pm2");
let allPids;
async function getPids(): number[] {
let pids = [];
try {
pids = await pm2.list();
} catch (err) {
console.error(err);
}
return list.map(process => process.pid);
}
(async () => {
allPids = await getPids();
console.log(allPids);
})();
Related
I would like to get some help because I just can not figure out how to use an async-await methods recursively in Node.js.
I am trying to create a function that returns all the files in all subfolders as an array using the file-system module.
I did saw a lot of examples online, but none of these used an array and than waited for an answer.
Thanks!
function checkFiles () {
const files = []
const getFiles = async dir => fs.readdir(`./${dir}`, { withFileTypes: true }, (err, inners) => {
if (err) {
throw new Error (err)
}
else {
inners.forEach(inner => {
inner.isDirectory() ? getFiles(`${dir}/${inner.name}`) : files.push(`file: ${inner.name}`);
});
};
});
getFiles('.')
if (files.length === 0) {
return 'no files'
}
else {
return files
}
}
console.log(checkFiles())
You are invoking getFiles asynchronously, and within getFiles you pass a callback to readdir instead of awaiting it.
What you should try is adding await to both lines:
function checkFiles() {
const files = []
const getFiles = async dir => {
try {
inners = await fs.readdir(`./${dir}`, { withFileTypes: true })
inners.forEach(inner => {
inner.isDirectory() ? getFiles(`${dir}/${inner.name}`) : files.push(`file: ${inner.name}`);
});
} catch {
// handle error
}
};
await getFiles('.')
if (files.length === 0) {
return 'no files'
}
return files
}
This will cause the program to halt when reaching getFiles(), and continue the execution only after it has finished, meaning files is ready for usage.
I would like to know to read the files and search for keyword sample in nodejs.
If keyword found, display the path
const allfiles = [
'C:\\Users\\public',
'C:\\Users\\public\\images',
'C:\\Users\\public\\javascripts\\index1.js',
'C:\\Users\\public\\javascripts\\index2.js'
]
const readFile = (path, opts = 'utf8') =>
new Promise((resolve, reject) => {
try{
let result=[];
fs.readFile(path, opts, (err, data) => {
if (err) reject(err)
else {
if(data.indexOf("sample")>=0){
result.push(data);
resolve(result);
}
}
})
}
catch (e) {
console.log("e", e);
}
})
const run = async () => {
allfiles.forEach(e=>{
const s = await readFile(e);
console.log(s);
})
}
run();
Expected Output
[
'C:\\Users\\public\\javascripts\\index1.js',
'C:\\Users\\public\\javascripts\\index2.js'
]
Some tips:
What happens when "sample" isn't found in readFile?
You're currently pushing the data into result instead of the path.
Think about what you're trying to accomplish with readFile. To me, what you want to do is see if that file has the word "sample", and return true if so and if not return false. So I'd name the function checkIfFileHasSample and have it return a boolean. Then in your run function, in the forEach you have the path, so that is where I'd add the path to a list of results.
Maybe you already realized this, but run is never actually called in your code sample. Ie. run() doesn't happen.
Solution:
You had some syntax errors and a tricky gotcha with async-await with run. For the syntax errors, it'll come with experience, but I'd also recommend using ESLint to help you catch them, as well as making sure your code is always properly indented.
const fs = require("fs");
const allfiles = [
"C:\\Users\\public",
"C:\\Users\\public\\images",
"C:\\Users\\public\\javascripts\\index1.js",
"C:\\Users\\public\\javascripts\\index2.js",
];
const checkIfFileHasSample = (path, opts = "utf8") =>
new Promise((resolve, reject) => {
fs.readFile(path, opts, (err, data) => {
if (err) {
reject(err);
} else {
if (data.includes("sample")) {
resolve(true);
} else {
resolve(false);
}
}
});
});
const run = async () => {
const results = [];
for (let i = 0; i < allFiles.length; i++) {
try {
const file = allFiles[i];
const hasSample = await checkIfFileHasSample(file);
if (hasSample) {
results.push(file);
}
} catch (e) {
console.log(e);
}
}
console.log(results);
};
run();
Essentially I have an async function containing a try/catch that calls another async function also containing a try catch, and I'm getting a bit confused about how to properly implement what I'm doing. Some "pseudocode" showing my current implementation:
const main = async () => {
try {
const test = await secondFunc();
console.log(test);
} catch(err) {
console.log('Found an error!');
console.log(err);
}
const secondFunc = async () => {
try {
await performSomeRequestExample();
} catch(err) {
if (err.x === 'x') {
doSomething();
} else {
//********
throw err;
//********
}
}
So what I'm trying to do is get the throw(err) (surrounded by the asterisks) to be caught by the catch in main() which will also call the console.log('Found an error!'), but what currently happens is the error is thrown from secondFunc(), the catch in main() is never hit and I get an unhandled promise rejection.
Any guidance on what I'm doing wrong?
My advice is to minimize using try/catch unless absolutely necessary. With async functions (or any functions that return a Promise object) you can usually simplify things by not worrying about try/catch blocks unless you need to do something specific with certain errors. You can also use .catch rather than try/catch blocks to make things easier to read.
For example your code above could be written like this:
const main = async () => {
const test = await secondFunc().catch(err => {
console.log("Found an error from secondFunc!", err);
throw err; // if you want to send it along to main's caller
});
if (test) {
console.log("Test", test);
}
};
const secondFunc = () => {
return performSomeRequestExample().catch(err => {
if (err.x === "x") {
doSomething();
} else {
throw err;
}
});
};
const performSomeRequestExample = () => Promise.reject("bad");
main().then(
() => console.log("worked"),
err => console.log("failed from main", err)
);
In secondFunc we don't need to use async since we can just return the promise coming back from performSomeRequestExample and handle any failures in the .catch.
You should use
const secondFunc = async () => {
performSomeRequestExample().then(res =>{
console.log(res);
})
.catch(err => {
console.log(err);
}
)
Add a return before the await of performSomeRequestExample.
const secondFunc = async () => {
try {
return await performSomeRequestExample();
} catch (err) {
if (err.x === 'x') {
console.log('x');
} else {
throw err;
}
}
}
or you can also use .catch() after the awaited function.
Another solution can be like this
const main = async() => {
try {
const test = await secondFunc();
console.log(test);
} catch(err) {
console.log('Found an error!');
console.log(err);
}
}
const secondFunc = async () => {
//return await performSomeRequestExample(); //for success
return await performSomeRequestExample(2); //for error
}
const performSomeRequestExample = async(abc=1) => {
return new Promise(function(resolve,reject){
if(abc ==1){
setInterval(resolve("yes"),400);
}else{
setInterval(reject("opps"),400);
}
});
}
main();
Test this code at this link:
https://repl.it/repls/JoyfulSomberTelevision
I use the Jest framework to create unit tests. When I run them. there is the message at the end:
"Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with --detectOpenHandles to troubleshoot this issue."
To exit, I use the command "--forceExit".
Also, I've tried to find an issue with --detectOpenHandles, but it didn't show anything.
I can't find what it hasn't closed, session or driver, or something else.
How could it be fixed?
const neo4j = require("neo4j-driver");
const driver = neo4j.v1.driver(
`bolt://${host}`,
neo4j.v1.auth.basic(username, password)
);
beforeAll(async () => {
await cleanDB();
});
afterAll(async () => {
await cleanDB();
driver.close();
});
async function cleanDB() {
await runQuery(`...query`);
}
async function runQuery(query) {
const session = driver.session();
return session
.writeTransaction(tx => tx.run(query))
.then(result => {
session.close();
return result;
})
.catch(error => {
session.close();
return { error };
});
}
describe(`bla-bla-bla`, function() {
beforeAll(async () => {
await dataBaseLoader(data);
});
test(`bla-bla-bla`, async function() {
const result = await runQuery(
'...query' );
//Body of Test
expect(result).toStrictEqual(expected);
});
There is no need to use async before function if you don't use await in body, also if function is not async access it without await
function cleanDB() {
runQuery(`...query`);
}
function runQuery(query) {
const session = driver.session();
return session
.writeTransaction(tx => tx.run(query))
.then(result => {
session.close();
return result;
})
.catch(error => {
session.close();
return { error };
});
}
and so on, check all your functions, maybe it will help
Im trying to use a while loop with my util() function (its commented out at the bottom of the code). When I try to run the program, I am stuck in an endless loop where i dont get farther than where I'm console logging out "getProjects running"
const axios = require("axios");
const _ = require("lodash");
axios.defaults.headers.common["Private-Token"] = "iTookMyPrivateKeyOut";
const user = "yshuman1";
let projectArray = [];
let reposExist = true;
async function getProjects() {
console.log("getProjects running");
await axios
.get(`https://gitlab.com/api/v4/users/${user}/projects`)
.then(function(response) {
const arr = _.map(response.data, "id").forEach(repo => {
projectArray.push(repo);
});
console.log(projectArray);
});
}
function deleteRepo(projectArray) {
console.log("array size", projectArray.length);
const arr = _.map(projectArray).forEach(item => {
axios
.delete(`https://gitlab.com/api/v4/projects/${item}`)
.then(() => {
console.log("deleted project ID: ", item);
})
.catch(error => {
console.log(error);
});
});
}
function util() {
getProjects()
.then(() => {
if (projectArray.length == 0) {
reposExist = false;
}
if (projectArray.length < 20) {
console.log("array is less than 20");
reposExist = false;
}
deleteRepo(projectArray);
})
.catch(error => {
console.log(error);
});
}
// while (reposExist) {
// util();
// }
The while loop is synchronous, while everything in any .then (or promise await) will be asynchronous. The initial thread will never terminate. Your code will simply queue up unlimited calls of getProjects which will only console.log.
The simple solution would be to figure out how often you want to call util (once a second? once every 5 seconds?) and await a Promise that resolves after that amount of time on each iteration.
let reposExist = true;
function util() {
console.log('running');
}
const resolveAfter5 = () => new Promise(res => setTimeout(res, 5000));
(async () => {
while (reposExist) {
util();
await resolveAfter5();
}
})();