how to define an async function in readline - node.js

I wrote an async function in nodejs that return value of a query in my database. I tested this query and it worked. but my problem is in the define of readline. when i run this code I get an error that :
const a = await Movie.find({}).sort('-year').where('year').gt(X).lt(Y).sort('rank')
^^^^^
SyntaxError: await is only valid in async function
how should I define readline function as async function?
this is my function :
async function returnMoviesBetweenXandY(){
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('enter the first number : ', (X) => {
rl.question('enter the second number : ', (Y) => {
const a = await Movie.find({}).sort('-year').where('year').gt(X).lt(Y).sort('rank')
const temp =await Promise.map(a, getTitle)
return temp
// rl.close();
});
});
}
returnMoviesBetweenXandY().then(function(result){console.log(result)})

Use async keyword before (X) => and (Y) => functions as lambda representation. Such as:
rl.question('enter the first number : ', async (X) => {
rl.question('enter the second number : ', async (Y) => {
const a = await Movie.find({}).sort('-year').where('year').gt(X).lt(Y).sort('rank')
const temp =await Promise.map(a, getTitle)
return temp
// rl.close();
});
});
Basically, the function should be marked async if you are using await keyword in the body of the function. In your case, you are using await keywords inside the lambda functions. So it should be marked as async.

Related

NodeJS reading files and putting lines as function arguments

How can I put data from an external txt file to function argument? I get undefined because reading files is asynchronous and the values which I give to the functions are undefined. How can I make it work? Each line is one variable.
let numberOfElephants;
let massOfElephants;
let elephantsOrderGiven;
let proposedOrder;
const readFile = () => {
return new Promise((resolve, reject) => {
const lineArray = [];
const readInterface = readline.createInterface({
input: fs.createReadStream("./slo1.in"),
output: process.stdout,
terminal: false,
});
readInterface
.on("line", (line) => {
lineArray.push(line);
})
.on("close", () => {
resolve(lineArray);
});
});
};
async function readAsync() {
const res = await readFile();
numberOfElephants= res[0],
massOfElephants= res[1],
elephantsOrderGiven= res[2],
proposedOrder= res[3],
}
console.log("read");
readAsync();
const sortElephants = (
numberOfElephants,
massOfElephants,
elephantsOrder,
directorsOrder
) => {}
sortElephants(
numberOfElephants,
massOfElephants,
elephantsOrderGiven,
proposedOrder
)

How solve this answer [AsyncFunction: response]?

I execute this function for a test in nodejs
const response = async () => {return await MyService.Adding({name})}
console.log(response)
but i get this: [AsyncFunction: response]
i want to use:
const res = await (async () => {
const response = await MyService.Adding({name})
return response
})()
console.log('RESPONDE ', res, expected)
If you are in the async function, just use await to run the other async functions.
Example
const res = await MyService.Adding({
name
})
Try:
// Just for example
const MyService = {
Adding: async (params) => params
}
async function main() {
const res = await MyService.Adding({
name: 'Your Name'
})
console.log(res)
}
main()
You are assigning a function to response
You want to eval the function in order to get the expected response.
Something like this:
let response2 = (async () => {return await MyService.Adding({name})})()
But if you are writing a small script, and you want to use await, you can't do it without an async function. So your script should be refactor to something like this:
(async () => {
const response = await MyService.Adding({name})
console.log(response);
})()
Your whole script can be written in the implicit evaluation of an async function and await will work.
It is not very preatty, but is better that managing callbacks

Error: await is only valid in async function when function is already within an async function

Goal: Get a list of files from my directory; get the SHA256 for each of those files
Error: await is only valid in async function
I'm not sure why that is the case since my function is already wrapped inside an async function.. any help is appreciated!
const hasha = require('hasha');
const getFiles = () => {
fs.readdir('PATH_TO_FILE', (err, files) => {
files.forEach(i => {
return i;
});
});
}
(async () => {
const getAllFiles = getFiles()
getAllFiles.forEach( i => {
const hash = await hasha.fromFile(i, {algorithm: 'sha256'});
return console.log(hash);
})
});
Your await isn't inside an async function because it's inside the .forEach() callback which is not declared async.
You really need to rethink how you approach this because getFiles() isn't even returning anything. Keep in mind that returning from a callback just returns from that callback, not from the parent function.
Here's what I would suggest:
const fsp = require('fs').promises;
const hasha = require('hasha');
async function getAllFiles() {
let files = await fsp.readdir('PATH_TO_FILE');
for (let file of files) {
const hash = await hasha.fromFile(i, {algorithm: 'sha256'});
console.log(hash);
}
}
getAllFiles().then(() => {
console.log("all done");
}).catch(err => {
console.log(err);
});
In this new implementation:
Use const fsp = require('fs').promises to get the promises interface for the fs module.
Use await fsp.readdir() to read the files using promises
Use a for/of loop so we can properly sequence our asynchronous operations with await.
Call the function and monitor both completion and error.

Asking multiple questions with readline nodejs

I am attempting to get both username and password from the CLI in a puppeteer project. I get it to ask one question and can use the value just fine, but when I do the second it just freezes on the input. It is almost like it is not actually closing and returning. I cannot seem to figure out what I am missing. I tried to declare the interface in the question method and then destroy it when close is called, but that did not work. I feel like I am close, but I cannot figure out what I am missing.
const login = require('../common/login.js');
userId = await login.getUserId();
console.log(userId) //works
password = await login.getPassword();
console.log(password) //does not work
login.js
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout
});
var methods = {};
const question = (promptText) => {
let response;
readline.setPrompt(promptText)
readline.prompt();
return new Promise((resolve, reject) => {
readline.on('line', (userInput) => {
console.log('hi');
response = userInput;
readline.close();
});
readline.on('close', () => {
console.log('bye');
resolve(response);
})
})
};
methods.getUserId = async() => {
let username = question("Username: ");
return username;
}
methods.getPassword = async() => {
let password = question("Password: ");
console.log(password);
return password;
}
module.exports = methods;
The readline.close() will close the streams. The below code works for me
const rli = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
function input(prompt) {
return new Promise((callbackFn, errorFn) => {
rli.question(prompt, (uinput)=> {
callbackFn(uinput);
}, ()=> {
errorFn();
});
});
}
const main = async () => {
amt = await input("Enter the amount to check: ");
doSomething(amt);
uname = await input("Enter your name: ");
doSomethingElse(uname);
rli.close();
};
main();

Node.js readline inside of promises

I'm trying to use the node.js package readline to get user input on the command line, and I want to pipe the entered input through promises. However, the input never gets through the then chain. I think the problem could come from the fact that the promises are fulfilled in the callback method, but I don't know how to solve that problem.
An example of this problem looks like this:
import rlp = require('readline');
const rl = rlp.createInterface({
input: process.stdin,
output: process.stdout
});
let prom = new Promise(resolve => {
rl.question('Enter input: ', input => rl.close() && resolve(input));
});
prom
.then(result => { console.log(result); return prom; })
.then(result => { console.log(result); return prom; })
.then(result => console.log(result));
If run in node.js, the question will appear once, after input has been entered the program just stops. I want it to wait until the first input has been entered, then it should print this input and ask for the next input.
Thanks in advance!
Once your promise is resolved, there's no use of waiting for that again. I also moved the rl.close() call to the end, as it's needed to be called only once.
const rlp = require('readline');
const rl = rlp.createInterface({
input: process.stdin,
output: process.stdout
});
function ask() {
return new Promise(resolve => {
rl.question('Enter input: ', input => resolve(input));
});
}
ask()
.then(result => { console.log(result); return ask(); })
.then(result => { console.log(result); return ask(); })
.then(result => { console.log(result); rl.close() });
Here's an answer from this question here for which I deserve no credit.
// Function
function Ask(query) {
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout
})
return new Promise(resolve => readline.question(query, ans => {
readline.close();
resolve(ans);
}))
}
// example useage
async function main() {
var name = await Ask("whats you name")
console.log(`nice to meet you ${name}`)
var age = await Ask("How old are you?")
console.log(`Wow what a fantastic age, imagine just being ${age}`)
}
main()
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const ask = (query) => new Promise((resolve) => rl.question(query, resolve));
ask('A: ').then(async (a) => {
const b = await ask('B: ');
const c = await ask('B: ');
console.log(a, b, c);
rl.close();
});
rl.on('close', () => process.exit(0));
Node.js 17 is here with new promise-based APIs for readline module:
import * as readline from 'node:readline/promises'
import { stdin as input, stdout as output } from 'process'
const rl = readline.createInterface({input, output})
const answer = await rl.question('What do you think of Node.js? ')
console.log(`Thank you for your valuable feedback: ${answer}`)
rl.close()
https://nodejs.org/api/readline.html#readline
node prompt.mjs
import { createInterface as createQuestionInterface } from 'readline';
const rl = createQuestionInterface({
input: process.stdin,
output: process.stdout
});
function questionLine(multiline, resolve, i, input, rl) {
if (!multiline) {
resolve(i);
} else {
if (input && !i) {
resolve(input);
} else {
return input + i + "\r\n";
}
}
return input;
}
function promptMultiLine(questionText) { // This is async by returning promise
return prompt(questionText, true);
}
async function prompt(questionText, multiline = false) {
return await (new Promise((resolve, reject) => {
let input = '';
rl.question(`${questionText}: `, (i) => {
input = questionLine(multiline, resolve, i, input, rl);
});
rl.on('line', (i) => {
input = questionLine(multiline, resolve, i, input, rl);
});
}));
}
async function run() {
const question = prompt("please enter response [enter to complete]");
console.log(question);
const questionMultiLine = promptMultiLine("please enter response [enter text and enter twice]");
console.log(questionMultiLine);
}
run();

Resources