Async await in node js with readline inside for loop - node.js

So I'm unable to force a for loop to wait for the stream to close before performing the next iteration.
It seems streaming data and async/await don't seem to get along (especially in for loops). Possibly one way around it may be to put everything in an infinite while loop (instead of a for loop) and use a POSIX mutex type method (where a flag is set, blocking opening a stream until the flag is reset at when the stream closes, and counters update). But there must be some kind of way to accomplish it with async/await.
Below is some test code:
async function bulk_search(an_array)
{
var name = "";
var found = false;
for(let i = 0; i < 10; i++)
{
for(let j = 0; j < 10; j++)
{
for(let k = 0; k < 10; k++)
{
console.log(i + ", " + j + ", " + k);
file_stream = fs.createReadStream(__dirname + '/a_directory/a_file.csv');
file_stream.on('error', function (err) {
return an_array;
});
csv_file = readline.createInterface({
input: file_stream
});
name = an_array[i][j][k];
found = false;
csv_file.on('line', function (line) {
if(name == line)
{
found = true;
csv_file.close();
}
});
await csv_file.on('close', function() {
console.log("Closing Stream");
if(found == false)
{
an_array[i][j][k] = "";
}
if((i == 9) && (j == 9) && (k == 9))
{
return an_array;
}
});
}
}
}
}

Related

Callback and event emitter functionality using NodeJS

Programme language is NodeJS
Steps ToDo:
1. The variable input has the input value. Extract n1 and n2 from the input.
2. Write a function to find the sum of all the multiples of n1 and n2, below and including 1000. This function should log the sum after 2 seconds.
3. Register an event named MyEvent for any instance of an event emitter, and bind a function named logInfo to it, which logs "Multiples of {n1} & {n2}" to the console and emit the event(Don't pass any parameters while emitting the event).
Constraints
Input: input, a string separated by space
Output: strings separated by newline
Note: Even though you got the exact output, the test cases will fail if you do not use the callback and event concepts as mentioned in the problem statement.
Sample Case 0
Sample Input For Custom Testing
100 1000
Sample Output:
Multiples of 100 & 1000
6500
Explanation
Multiples of 100 are 100,200,300,......1000 and multiples of 1000 is 1000 in below and including 1000.
Sum = (100+200+............1000) + 1000
Sum = 6500
Sample Case 1
Sample Input For Custom Testing
500 1200
Sample Output:
Multiples of 500 & 1200
1500
I Tried below code :
process.stdin.resume();
process.stdin.setEncoding("ascii");
var input = "";
process.stdin.on("data", function (chunk) {
input += chunk;
});
process.stdin.on("end", function () {
let _input = input.split (" ");
let a = parseInt(_input[0]);
let b = parseInt(_input[1]);
console.log("Multiples of " + a + " & " + b);
var sum = 0;
for (var x = 0; x < 1000; x++)
{
if (x % a === 0 || x % b === 0)
{
sum += x;
}
}
console.log(sum);
});
Code Test out:
Case 1
Input (stdin)
4 6
Your Output (stdout)
Multiples of 4 & 6
165834
Expected Output
Multiples of 4 & 6
208666
===============================================
Case 2
Input (stdin)
3 5
Your Output (stdout)
Multiples of 3 & 5
233168
Expected Output
Multiples of 3 & 5
267333
Please help me for this code. My output is not match with this logic.
process.stdin.resume();
process.stdin.setEncoding("ascii");
var input = "";
process.stdin.on("data", function (chunk) {
input += chunk;
});
process.stdin.on("end", function () {
const myArr = input.split(" ");
const EventEmitter = require('events');
var eventEmitter = new EventEmitter();
let sum=0;
let a = myArr[0];
let b = myArr[1];
for(let i=3; i<=1000; i++){
if(i%a==0){
sum += i
}
if(i%b==0){
sum+=i
}
}
eventEmitter.on('MyEvent', function(){
setTimeout(function(){
console.log("Multiples of " + a + " & "+ b);
console.log(sum);},5000);
});
eventEmitter.emit('MyEvent');
});
I got the right solution.
process.stdin.resume();
process.stdin.setEncoding("ascii");
var input = "";
process.stdin.on("data", function (chunk) {
input += chunk;
});
process.stdin.on("end", function () {
const EventEmitter = require('events');
let data = input.split(" ");
n1 = data[0];
n2 = data[1];
// console.log(n1,n2);
let result = 0;
const sum = () => {
for (let i = 0; i <= 1000; i++) {
if (i % n1 == 0) {
result += i;
}
}
for (let j = 0; j <= 1000; j++) {
if (j % n2 == 0) {
result += j;
}
}
console.log(result);
}
setTimeout(sum, 2000);
const event = new EventEmitter();
event.on("MyEvent", () => {
console.log(`Multiples of ${n1} & ${n2}`);
})
event.emit("MyEvent");
});
I hope below code will help you and will give expected output. Thanks! :)
process.stdin.resume();
process.stdin.setEncoding("ascii");
var input = "";
process.stdin.on("data", function (chunk) {
input += chunk;
});
process.stdin.on("end", function () {
const myArr = input.split(" ");
const EventEmitter = require('events');
var eventEmitter = new EventEmitter();
let sum=0;
let a = myArr[0];
let b = myArr[1];
for(let i=3; i<=1000; i++){
if(i%a==0){
sum += i
}
if(i%b==0){
sum+=i
}
}
eventEmitter.on('MyEvent', logInfo);
function logInfo(input) {
console.log("Multiples of " + a + " & "+ b);
console.log(sum);
}
eventEmitter.emit('MyEvent', "");
});
Check below solution
process.stdin.resume();
process.stdin.setEncoding("ascii");
var input = "";
process.stdin.on("data", function (chunk) {
input += chunk;
});
process.stdin.on("end", function () {
const myArr = input.split(" ");
const EventEmitter = require('events');
var eventEmitter = new EventEmitter();
let sum=0;
let a = myArr[0];
let b = myArr[1];
for(let i=3; i<=1000; i++){
if(i%a==0){
sum += i
}
if(i%b==0){
sum+=i
}
}
eventEmitter.on('MyEvent', logInfo);
function logInfo(input) {
console.log("Multiples of " + a + " & "+ b);
console.log(sum);
}
eventEmitter.emit('MyEvent', "");
});
I have only call console as async function kindly avoid my mistake.
process.stdin.on("end", function () {
// Enter your code here
const myArr = input.split(" ");
const EventEmitter = require('events');
var eventEmitter = new EventEmitter();
let sum=0;
let a = myArr[0];
let b = myArr[1];
for(let i=3; i<=1000; i++){
if(i%a==0){
sum += i
}
if(i%b==0){
sum+=i
}
}
setTimeout(function(){
console.log(sum);
},2000)
eventEmitter.on('MyEvent', logInfo);
function logInfo() {
console.log("Multiples of " + a + " & "+ b);
}
eventEmitter.emit('MyEvent');
});

Node.js for loop output only last item from JSON

The code below only output the last result, I don't get it. I check if the updateDate item contains 2020-05 both items does and I get only the last one. The loop is not looping :)
const briefing = [
{
"updateDate": "2020-05-05T00:00:00.0Z",
},
{
"updateDate": "2020-05-06T00:00:00.0Z",
},
{
"updateDate": "2020-05-13T00:00:00.0Z",
}
];
let date = new Date();
var formattedYearMonth = date.getFullYear() + '-' + ('0' + (date.getMonth()+1)).slice(-2) + '-';
for (var i = 0; i < briefing.length; i++) {
var jsonDate = briefing[i].updateDate;
if (jsonDate.includes(formattedYearMonth)) {
var response = JSON.stringify(briefing[i]);
}
}return response;
}
for (var i = 0; i < briefing.length; i++) {
var jsonDate = briefing[i].updateDate;
if (jsonDate.includes(formattedYearMonth)) {
var response = JSON.stringify(briefing[i]); // <==== THIS IS WHERE YOUR PROBLEM LIES
}
}return response;
The loop is actually looping :). But for every run of the loop, you are resetting the value of response.
--EDITED--
For the response to be an array, you need to modify your code as
let response = [];
for (var i = 0; i < briefing.length; i++) {
var jsonDate = briefing[i].updateDate;
if (jsonDate.includes(formattedYearMonth)) {
response.push(JSON.stringify(briefing[i]));
}
}
return response;

Batch 500 writes into firestore loop from json file

Using some inspiration I got from this thread and reply I tried to get my loop working which is to write into firestore in batches. But somehow I only can only update 1 document even if I can see I iterate through different values from my array. I load data into an array and work from there.
const db = admin.firestore();
const jsonStream = StreamArray.withParser();
let arr = []
jsonStream.on('data', ({ key, value }) => {
arr.push(value);
});
jsonStream.on('end', () => {
var counter = 0;
var commitCounter = 0;
var batches = [];
arr.forEach((a, ind) => {
batches[commitCounter] = db.batch();
if (counter <= 498) {
var thisRef = db.collection('Testing').doc(a.id);
console.log("id")
console.log(a.id);
batches[commitCounter].set(thisRef, { ...a });
counter = counter + 1;
} else {
counter = 0;
commitCounter = commitCounter + 1;
batches[commitCounter] = db.batch();
}
})
for (var i = 0; i < batches.length; i++) {
if(i==0)
{
console.log(batches[0])
}
batches[i].commit().then(function () {
console.count('wrote batch');
});
}
});
const filename = path.join(__dirname, 'mydata.json');
fs.createReadStream(filename).pipe(jsonStream.input);
Following line gets executed on each iteration, which essentially "resets" your batch on each round:
batches[commitCounter] = db.batch();
So at the end each of your batches will only contain one document write.

NodeJS: How to wait for the HTTP Get request is complete in For Loop?

I have a for loop function in NodeJS. I would like to wait until the result of Http Get request is completed in For Loop before it executes the next iteration, how do I achieve that?
for (let k=0; k<fd.length; k++) {
url = fd[k].nct_id;
HttpSearch({condition: url}).then(trials => {
//Get the result first before execute the next iteration
console.log(trials);
});
}
You should make the for-loop async:
const main = async () => {
for (let k = 0; k < fd.length; k++) {
const url = fd[k].nct_id;
const trials = await HttpSearch({ condition: url });
console.log(trials);
}
};
main().catch(console.error);
This will cause the loop to "pause" at each HttpSearch.
I will do like this
let k = 0 ;
let len = fd.length;
for (; k > len;) {
let url = fd[k].nct_id;
let subs = await HttpSearch({condition: url});
console.log(subs);
k++
}
or like this with promise
let url;
let promiseChain = Promise.resolve();
for (let i = 0; i < fd.length; i++) {
url = fd[k].nct_id;
// you need to pass the current value of `url`
// into the chain manually, to avoid having its value
// changed before the .then code accesses it.
const makeNextPromise = (url) => () => {
HttpSearch({condition: url})
.then((result) => {
// return promise here
return result
});
}
promiseChain = promiseChain.then(makeNextPromise(url))
}
This is using recursion, which calls next, once previous is finished
var limit = fd.length;
var counter = 0;
HttpSearch({condition: fd[0].nct_id;}).then(yourCallBack);
function yourCallBack(trials){
console.log(trails);
if(counter == limit)
return console.log('Done')
HttpSearch({condition: fd[counter].nct_id;}).then(yourCallBack);
counter++;
}

node js function.then in not a function using q

Hello its so wired i am trying to do async function but when i use it i get error
using q
on package json
"q": "^1.4.1"
TypeError: helper.setNextUserNewsAction(...).then is not a function
this is my helper
module.exports = function() {
return {
setNextUserNewsAction: setNextUserNewsAction
}
}();
function setNextUserNewsAction(minutesToSet){
var defer = q.defer();
var x = minutesToSet;
var d = new Date();
var nextNews = new Date(d.getTime() + x*60000);
var minutes = nextNews.getMinutes();
var newMinutesToSet = 0;
for (var i = 0 , j = minutesToSet; j <= 60; i+=minutesToSet,j+=minutesToSet) {
if (minutes > i && minutes < j)
return newMinutesToSet = (i % 60);
}
nextNews.setMinutes(newMinutesToSet);
nextNews.setSeconds(00);
var NextNewsAction = {
AccessDate: nextNews,
Type: 'News',
Current: 1
}
defer.resolve(NextNewsAction);
return defer.promise;
}
and when i call this function in my controller it send me that error
var helper = require('../helpers/playlist');
helper.setNextUserNewsAction(15).then(function(action){
console.log(action);
},function(err){
console.log(err);
});
i have also try doing that with try and catch and still same error
well its not the first time or the 20 i am using q
hope somebody can help
The problem is that you are returning something from the for loop:
for (var i = 0, j = minutesToSet; j <= 60; i += minutesToSet, j += minutesToSet) {
if (minutes > i && minutes < j)
return newMinutesToSet = (i % 60);
}
So the setNextUserNewsAction function is not returning a promise, therefore there is no .then().
Try this:
var q = require('q');
module.exports = function() {
return {
setNextUserNewsAction: setNextUserNewsAction
}
}();
function setNextUserNewsAction(minutesToSet){
var defer = q.defer();
var x = minutesToSet;
var d = new Date();
var nextNews = new Date(d.getTime() + x*60000);
var minutes = nextNews.getMinutes();
var newMinutesToSet = 0;
for (var i = 0, j = minutesToSet; j <= 60; i += minutesToSet, j += minutesToSet) {
if (minutes > i && minutes < j) {
newMinutesToSet = (i % 60);
}
}
nextNews.setMinutes(newMinutesToSet);
nextNews.setSeconds(00);
var NextNewsAction = {
AccessDate: nextNews,
Type: 'News',
Current: 1
}
defer.resolve();
return defer.promise;
}

Resources