Nodejs fs.createReadStream event error - javascript

I am trying to read data from a file very quickly (data from an ADC). The conversion is started on opening the file, and finished at close. I need to wait opening the file again, and wait for the currently conversion to complete.
My problem is, that when i am opening the file very quickly nodejs wont caught the expected events. Any clue how to fix this?
node.on('input', function(){
readStream = fs.createReadStream(path.location,{encoding: 'utf8'});
if (readyFlag == 1) {
readStream.on('data',(data) => {
data = {payload: data/1000};
node.send(data);
console.log(`data: ${data}`);
})
}
readStream.on('open', () => {
console.log("file opened");
readyFlag = 0;
})
readStream.on('close', () => {
console.log("file closed");
readyFlag = 1;
})
readStream.on('error', (err) => {
console.log(err);
})
})
I end up with the file being opened all the time.

So looks to me like the problem here is the context of readStream - it's not local to the input callback meaning each message will overwrite the reference to the previous stream.
The fact this starts to fail when you increase the frequency of the messages seems logical to me because the stream hasn't had a chance to finish so readyFlag is never reset.
The fix for this should literally a one liner, make the stream a local var
const readStream = ...

I think I have solved it. The readyFlag has to be global to the input scope, otherwise it would not work. I moved the 'open' event inside the the if statement, which is checking for the readyFlag. That seemed to do the problem. Now the system dont hang, and the file is only being opened, when its done reading and have closed the previously open section.
Here is the code:
var readyFlag = 1;
node.on('input', function(msg){
const readStream = fs.createReadStream(path.location,{encoding: 'utf8'});
if (readyFlag == 1) {
readStream.on('data',(data) => {
data = {payload: data/1000};
node.send(data);
console.log('data read');
readyFlag = 0;
})
readStream.on('open', () => {
console.log("file opened");
})
}
readStream.on('close', () => {
console.log("file closed");
readyFlag = 1;
})
readStream.on('error', (err) => {
console.log(err);
})
})

Related

socket in nodejs will not close no matter what

So I'm trying to make a script that will connect a bot to a kahoot. However I can only use a certain name one time otherwise I will get a duplicate name error, even after closing all sockets, terminating sockets, removing listeners, etc. Is there something I'm missing?
Edit: added the cleanup on process end that still doesn't work
var Kahoot = require("kahoot.js-latest");
var colors = require('colors');
var bot = new Kahoot;
function cleanup() {
bot.leave();
bot.removeAllListeners();
bot.socket.close();
bot.socket.terminate();
}
bot.join(process.argv[2], "a")
.then(() => {
console.log("Joining...".cyan);
})
.catch((err) => {
console.log(err);
cleanup();
});
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach((eventType) => {
process.on(eventType, (code) => {
for (n in bots) {
cleanup();
}
console.log("Exiting Process with code: ".yellow + code);
})
})
After terminating the process and trying to run it again with the same name, I get a duplicate name error even though surely that connection should be destroyed by now
Edit: the error:
{
description: 'Duplicate name',
type: 'loginResponse',
error: 'USER_INPUT'
}

JavaScript fetch is delayed

I have an Express server waiting for my website to do something. When my site does something, a shell script should be called on the Express server. The problem is: The shell script is only run after the "confirm window" has been accepted or denied. I want the fetch to happen as soon as possible. I wouldn't even need to get anything from the Express server, I just want to signal Express to run the shell script as soon as possible.
I have this code on the website:
messaging.onMessage(function (payload){
fetch("http://localhost:9000/testAPI")
.then(res => res.text())
.then(res => console.log("something:" + res));
var r = confirm(callingname + " is calling.");
if (r == true) {
window.open(payload.data.contact_link, "_self");
} else {
console.log("didn't open");
}
});
I have this code on the backend:
var express = require("express");
var router = express.Router();
router.get("/", function(req,res,next){
const { exec } = require('child_process');
exec('bash hi.sh',
(error, stdout, stderr) => {
console.log(stdout);
console.log(stderr);
if (error !== null) {
console.log(`exec error: ${error}`);
}
});
res.send("API is working");
});
module.exports = router;
confirm() is blocking, and you only have a single thread. This means confirm() will stop the world for your application, preventing fetch() from doing anything.
As the simplest possible fix, you can try delaying the moment when confirm() is invoked. This would allow fetch() to get the request out.
messaging.onMessage(function (payload) {
fetch("http://localhost:9000/testAPI")
.then(res => res.text())
.then(text => console.log("something:" + text));
setTimeout(function () {
if (confirm(`${callingname} is calling.`)) {
window.open(payload.data.contact_link, "_self");
} else {
console.log("didnt open");
}
}, 50);
});
Other options would be to put confirm() into one of the .then() callbacks of fetch, or to use a non-blocking alternative to confirm(), as suggested in the comments.

Posting JSON request and reading EventStreams in Angular11

Tried following the article below to read eventstreams. Instead of using formData like it is done in the article, I'm using Json to post. It works smoothly with a 200 response. Even tells that some kb of data was sent over the wire, but the eventstream tab shows nothing. The same curl works on my terminal.
https://medium.com/swlh/how-do-server-sent-events-sse-or-eventsource-work-in-angular-e9e27b6a3295
As shown in the article
return Observable.create((observer) => {
const eventSource = this.sseService.getEventSourceWithPost(url, data);
// Launch query
eventSource.stream();
// on answer from message listener
eventSource.onmessage = (event) => {
this.zone.run(() => {
observer.next(event.progress);
});
};
eventSource.onerror = (error) => {
this.zone.run(() => {
observer.error(error);
});
};
});
Changing this part to
return Observable.create((observer) => {
const eventSource = this.sseService.getEventSourceWithPost(url, data);
// Launch query
eventSource.stream();
// on answer from message listener
eventSource.addEventListener('EVENT_NAME_FROM_STREAM', (event) => {
this.zone.run(() => {
observer.next(event.data);
});
};
});
Got the data to show up. But in the network tab I still don't see the events.

Using Discord.js to get all of the messages sent since the bot went offline

So I am making a bot that will store all of the messages sent in a channel into a txt file on my computer. Since I don't have my computer on all the time and I run the bot on my computer it leaves gaps in messages stored in the .txt file. I am trying to make it so that my bot will get all the messages sent since it went offline and store all of them in my file. I created a txt file that saves the message id of every message, it will overwrite the last message so its basically just a file with one message id in it. When my bot starts a boolean variable is instantiated to false and will be set to true once the startup procedure has been completed. This is what I have so far:
var latest;
var beenRunning = false;
bot.on('message', msg => {
latest = msg.id;
if(beenRunning == false) {
msg.channel.messages.fetch(latest, {limit: 100})
.then(messages =>
//code to get messages since last online
)
.catch(console.error);
beenRunning = true;
}
else {
messageTest(msg);
}
fs.writeFile('lastMsg.txt', latest, (err) => {
if (err) throw err;
})
});
I am not sure how to get every message since going offline using the fetch() method. How would I do this?
Not sure how you are structuring your lastMsg.txt, so I just used json.
Might be a bit slow since it'll be a bigger file and its using a lot of array higher functions
let logged = require("./lastMsg.json");
let beenRunning;
bot.on('message', msg => {
if (!beenRunning) {
msg.channel.messages.fetch({ limit: 100 })
.then(messages => {
const reduced = messages
.map(e => ({ id: e.id, content: e.content }))
.filter(e => {
return logged.find(l => l.id === e.id && l.content === e.content);
});
logged = logged.concat(reduced.array());
beenRunning = true;
})
.catch(console.error);
} else {
messageTest(msg);
}
fs.writeFile('lastMsg.json', JSON.stringify(logged), (err) => {
if (err) throw err;
})
});
Initalize your ./lastMsg.json to
[]

Firebase response depending on Firestore Query does not work

Depending on whether there is an entry in Cloud Firestore with the correct DocumentId. However, this does not work because my function sends the status 200 before even finishing the query. So how can I get that working?
Here is my code:
access = false;
admin.firebase().collection("tuere").doc(door).collection("eintritt").get().then((snapshot) => {
snapshot.forEach((doc) => {
if(doc.id === uid){
access = true;
console.log("May open door " + uid);
}
});
}).catch((err) => {
console.log(err);
});
res.status(200).send(access);
When I open the Tab in Chrome and let it load "false" appears, but when I wait like 15 Seconds "May open door (uid)" appears in the Logs.
How can I solve this problem and how can i get my function to run faster?
You should send the HTTP response when the promise resolves, so within the then of the query promise: like that:
access = false;
admin.firebase().collection("tuere").doc(door).collection("eintritt").get()
.then((snapshot) => {
snapshot.forEach((doc) => {
if(doc.id === uid){
access = true;
console.log("May open door " + uid);
}
});
res.status(200).send(access);
}).catch((err) => {
console.log(err);
res.status(500).send(err);
});
Also, you should send an HTTP response in case of error, this is why I added res.status(500).send(err); in the catch
I would suggest you look this video from Doug Stevenson: https://www.youtube.com/watch?v=7IkUgCLr5oA
Also there is a point which surprises me: shouln't you use
admin.firestore().collection("tuere").doc(door)....
instead of
admin.firebase().collection("tuere").doc(door)
I have to look in the reference, but I have the feeling that admin.firebase() does not exist.

Categories

Resources