Read the statement by Michael Teeuw here.
Multiple requests within one function
-
Hello community :-)
I’m kinda despairing with this problem :-(
The idea: requesting the system temperatures of all raspberrys listed in the config file (they are all running a flask server)
But I can’t get the object working.node_helper gets the object from my config file:
{ module: 'getTemps', header: 'RPi Temperatures', position: 'top_right', config: { devices: [ { url: 'http://10.0.0.83:2222/temp', name: 'Alarmpi' }, { url: 'http://10.0.0.25:2222/temp', name: 'Mediapi' }, { url: 'http://10.0.0.25:2222/temp', name: 'Camerapi' } ] } },
my node_helper.js:
getJSON: function(object) { var self = this; var data = object; console.log(data); for (var key in data) { console.log(data[key]); request({url: data[key].url, method: 'GET'}, function(error, response, body) { if (!error && response.statusCode == 200) { data[key].temp=body; console.log(body); console.log(data); } else { console.log(" Error: " + response.statusCode); data[key].temp = 'offline'; } }); } console.log(data); self.sendSocketNotification('received_values', data); }
just one run creates two outputs and the final content of “data” is missing the temperature values.
And as shown in the console output, the received temperature value is always added (it looks like temporary) to the last object in the list.[ { url: ‘http://10.0.0.83:2222/temp’, name: ‘Alarmpi’ },
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Mediapi’ },
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Camerapi’ } ]
{ url: ‘http://10.0.0.83:2222/temp’, name: ‘Alarmpi’ }
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Mediapi’ }
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Camerapi’ }
[ { url: ‘http://10.0.0.83:2222/temp’, name: ‘Alarmpi’ },
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Mediapi’ },
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Camerapi’ } ]
51.0
[ { url: ‘http://10.0.0.83:2222/temp’, name: ‘Alarmpi’ },
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Mediapi’ },
{ url: ‘http://10.0.0.25:2222/temp’,
name: ‘Camerapi’,
temp: ‘51.0’ } ]
51.5
[ { url: ‘http://10.0.0.83:2222/temp’, name: ‘Alarmpi’ },
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Mediapi’ },
{ url: ‘http://10.0.0.25:2222/temp’,
name: ‘Camerapi’,
temp: ‘51.5’ } ]
59.1
[ { url: ‘http://10.0.0.83:2222/temp’, name: ‘Alarmpi’ },
{ url: ‘http://10.0.0.25:2222/temp’, name: ‘Mediapi’ },
{ url: ‘http://10.0.0.25:2222/temp’,
name: ‘Camerapi’,
temp: ‘59.1’ } ](Mediapi and Camerapi have the same IP in this example)
thanks for your help :-)
-
@blaukon you assume that you have the value data already when you send the variable data to your module, but request is asynchronous and therefore you get most likely the data after you send the result
-
As @strawberry-3-141 mentioned, the
sendSocketNotification()
function is called, before the callback function of your request is execuded and the content ofdata
is created.You could either call the
sendSocketNotification()
function inside the callback function of the request or put thedata
variable into a promise (which is a much more elegant approach and produces good-readable asynchronous code).There are good explanations for promises, just google “promises simple explanation” (or similar).
I can recommend this one: https://coligo.io/javascript-promises-plain-simple/Edit:
Oh, and I would recommend the Bluebird.js library for promises. http://bluebirdjs.com/ -
yeey, I got it working, although I don’t know why :P
var NodeHelper = require("node_helper"); var request = require('request'); var Promise = require("promise"); var result = new Array(); module.exports = NodeHelper.create({ start: function() { console.log("Starting node_helper for module [" + this.name + "]"); }, // subclass socketNotificationReceived socketNotificationReceived: function(notification, payload){ if (notification === 'get_values') { this.getJSON(payload); } }, requestp: function(url, key, name) { return new Promise(function (resolve, reject) { request({url:url, method: 'GET'}, function (err, res, body) { if (err) { return reject(err); } else if (res.statusCode !== 200) { err = new Error("Unexpected status code: " + res.statusCode); err.res = res; return reject(err); } result.push({url: url, name: name, temp: body}); resolve(body); }); }); }, getJSON: function(object) { var self = this; for (var key in object) { //console.log(object[key]); self.requestp(object[key].url, key, object[key].name).then(function (info) { //console.log(info); }, function (err) { console.error("%s; %s", err.message, url); console.log("%j", err.res.statusCode); }); } //console.log(result); self.sendSocketNotification('received_values', result); result = []; } });
I wasn’t able to add a “temp” property to the original object - it was actually added, but it did not want to work outside the .then function :(