Reputation: 5
Im pretty new to programming and im trying to make efforts - probably this question is not really worth to be asked but I am not making any progress since.. way too long.
I am trying to do a discovery search on all devices that are connected to my local network in a node.js script.
I found this npm module which should do the job: https://www.npmjs.com/package/local-devices/v/3.0.0
So I just tried to copy-paste the example they have given to search my network for all devices:
const find = require('local-devices');
// Find all local network devices.
find().then(devices => {
devices /*
[
{ name: '?', ip: '192.168.0.10', mac: '...' },
{ name: '...', ip: '192.168.0.17', mac: '...' },
{ name: '...', ip: '192.168.0.21', mac: '...' },
{ name: '...', ip: '192.168.0.22', mac: '...' }
]
*/
})
But if I run the script now, nothing happens.
What i've tried so far: 1. I tried to save the output in a constant and tried to output this on a console
const found = find().then(devices => {
devices
/*[
{ name: '?', ip: '192.168.0.10', mac: '...' },
{ name: '...', ip: '192.168.0.17', mac: '...' },
{ name: '...', ip: '192.168.0.21', mac: '...' },
{ name: '...', ip: '192.168.0.22', mac: '...' }
]
return devices
})
console.log(found);
then the console output is Promise { <pending> }
. I couldnt figure out what to do with this yet.
arp -a
which, if executed in the command line, lists all ip adresses of all devices in the network in the terminal. So it basically does exactly what I want, but I need to work with that output in the following code (I need to find one specific ip adress of a smart plug from this list, but that is a different story). How can I take this command line argument, and execute it in my javascript code/ my node.js script, and save the output in a variable/const?
Best regards, Michael
Upvotes: 0
Views: 468
Reputation: 2502
When a function returns a Promise
it means that it is running asynchronously (there are various tutorials on the web about this). Long story short, the find()
function will return immediately with a Promise
object and then it will go and find the ip addresses, and once it finds it it will populate the Promise
(i.e. fulfill
it).
The then()
part is a callback to be executed once the Promise is fulfilled. So what you can do is:
const find = require('local-devices');
async function findIP() {
// Find all local network devices.
const found = find().then(devices => {
console.log(devices);
})
await found;
}
findIP();
Essentially the await
is telling JS to wait until the found
Promise object is fulfilled - right now JS is just exiting before the ip addresses are found.
Upvotes: 1
Reputation: 721
The issue you're facing is very common in the JS world. I'll try my best to explain it to you. It's called concurrency, and in very simple terms it means that two or more processes (or threads) run together, but not at the same time. Only one process executes at once.
Even simpler: it means that the code inside the then
callback is being delayed for when the CPU is free.
What you see when printing the found
object is a Promise { <pending> }
. It's an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. It allows you to associate handlers/callbacks with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.
But why do we care? you might say. Well, it's because you simply can think of find
function as a "linear" operation. You have to imagine that you pass some sort of callback (through then
) that will be executed as soon as it finds all local network devices.
So you could rewrite your code like:
const find = require('local-devices');
// Find all local network devices.
find().then(devices => {
console.log(devices) /*
[
{ name: '?', ip: '192.168.0.10', mac: '...' },
{ name: '...', ip: '192.168.0.17', mac: '...' },
{ name: '...', ip: '192.168.0.21', mac: '...' },
{ name: '...', ip: '192.168.0.22', mac: '...' }
]
*/
})
But what if you wanted to avoid the callback hell
Well, JavaScript offers the async
& await
keywords to help you with that. It's just a fancy way of hiding/dealing with callbacks.
First, we need to be inside an async
function, it's a requirement to use await
. In the example below, I'll use a self-invoking function to makes things nicer. We can then use await
to get the result from the find
function:
(async () => {
const find = require('local-devices');
// Find all local network devices.
const devices = await find()
console.log(devices)
})()
Upvotes: 0
Reputation: 6467
Certainly worth asking! JS can be a confusing language to learn.
If a function returns a Promise (as find
does) then logging what it returns is not normally very useful. A Promise is something which will at some point be able to potentially give some sort of useful value.
The .then
part of your function is where you can use the value that the promise contains. A Promise will run the function contained in .then
once it has got the value back. So doing something like:
const find = require('local-devices');
// Find all local network devices.
find().then(devices => {
console.log(devices);
})
Means that when the function which finds the devices has got a value back, it will log that value.
Upvotes: 0