I try to get the response of the http-request to my variable "temperature" but it doesnt work, i already tried it with callbacks but im not really familiar with it so i cant solve my problem right now. Maybe someone has an idea?
thanks and best regards :-)
var temperature = '';
http.get(url, function(res) {
//console.log("Got response: " + res.statusCode);
var bodyarr = [];
res.on('data', function(chunk){
bodyarr.push(chunk);
});
res.on('end', function(){
//console.log(*/bodyarr.join('').toString());
temperature = bodyarr;
});
enter code here
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
console.log(temperature);
The issue is about asynchronicity here; the temperature object is undefined at that point since the log method is called before the request is done. Use the http.request as it's asynchronous; it takes a callback as parameter which you pass to response.end if you want to have the complete response:
//The url for example is 'www.random.org/temperatures/?min=1&max=100'
var options = {
host: 'www.random.org',
path: '/temperatures/?min=1&max=100'
};
var temperature = '';
var http = require('http');
callback = function(res) {
var bodyarr = [];
res.on('data', function (chunk) {
bodyarr.push(chunk);
});
res.on('end', function () {
console.log(req.data);
console.log(bodyarr);
temperature = bodyarr.join();
});
}
var req = http.request(options, callback).end();
Related
I am trying to write a AWS Lambda function with Nodejs.
Inside the code I have to call a API, wait for the response and do other things with that data (I haven't still write anything about this)
NOTE: sorry about declaring customerTAX as global, but I prefer to get the lambda function to work with and after, try to return the value from the function isself.
This is the code:
'use strict';
var customerTAX;
const https = require('https');
const options = {
host: 'xxxxxxx.com',
port: 443,
path: '/yyyyyyy.json',
method: 'POST',
headers: {
'Content-Type': 'application/graphql',
}
};
exports.handler = async (event) => {
const body = JSON.parse(event.body);
const orderId = body.id;
const customerId = body.customer.id;
console.log('ORDER ID: ' + orderId);
console.log('CUST ID: ' + customerId);
const query = `xxxxxxxxxxxxxxxxxxxx`;
//I CAN SEE ALL LOGS OF THIS FUNCTION IN CLOUDWATCH
await getCustomerTAX(query);
//I CAN'T SEE NOTHING BELOW THIS LINE IN AWS CLOUDWATCH
console.log('CUST TAX: ' + customerTAX);
if (customerTAX != null) {
console.log('LETs GO TO SAVE IT')
} else {
console.log('NOTAX: No customerTAX');
}
const response = {
statusCode: 200,
body: JSON.stringify(event.body),
};
return response;
};
var getCustomerTAX = function(query) {
return new Promise(function(resolve, reject) {
var req = https.request(options, function(res) {
res.setEncoding('utf8');
var bodyRaw = '';
res.on('readable', function () {
var chunk = this.read() || '';
bodyRaw += chunk;
console.log('getTAX CHUNK (' + Buffer.byteLength(chunk) + ' bytes): ' + chunk);
});
res.on('end', function () {
const body = JSON.parse(bodyRaw);
if (body.TAX.value != null) {
customerTAX = body.TAX.value;
} else {
customerTAX = null;
}
console.log("getTAX END: " + customerTAX);
resolve;
//console.log('body: ' + Buffer.byteLength(body) + ' bytes');
});
});
//handle the possible errors
req.on('error', function(e) {
console.log("ERROR: " + e);
reject(e);
});
//do the request
req.write(query);
//finish the request
req.end();
});
};
Function getCustomerTAX works perfectly, but I don't know why my lambda function is "finished" in this line, and I can't see more console-logs in cloudwatch.
Hope your answer and thanks a lot.
For starters in getCustomerTax(), resolve; needs to be resolve();.
It's a function. You need to call it.
Without calling resolve(), the promise is never resolved and thus await getCustomerTax() never finishes and the lines after it are never executed.
FYI, the request-promise module will automatically do a lot of what you have in getCustomerTax() (make an http request, get the response, handle all possible errors and return a promise that represents the result).
EDIT Jan, 2020 - request() module in maintenance mode
FYI, the request module and its derivatives like request-promise are now in maintenance mode and will not be actively developed to add new features. You can read more about the reasoning here. There is a list of alternatives in this table with some discussion of each one. I have been using got() myself and it's built from the beginning to use promises and is simple to use.
I am trying to pass on an array of strings from the 'LaunchRequest' to the 'TellAJoke' intent.
My problem is that this.attributes['joke'] is always undefined in the 'TellAJoke' function.
'LaunchRequest': function() {
var url = "https://www.reddit.com/r/jokes/top.json?limit=1";
var self = this;
var request = https.get(url, function(res) {
var body = '';
res.on('data', function(chunk){
body += chunk;
});
res.on('end', function(){
var redditResponse = JSON.parse(body);
redditResponse['data'].children.forEach(function(child) {
jokeArray.push({
title: child.data.title,
text: child.data.selftext
});
});
// Assinging the filled jokeArray to the session variable
self.attributes['joke'] = jokeArray;
self.emit(':saveState', true);
}).on('error', function(e){
self.emit(':tell', "Error");
console.log("Got an error: ", e);
});
this.emit('TellAJoke');
});
},
'TellAJoke': function() {
this.attributes['randomNumber'] = Math.floor(Math.random() * 8) +0;
//This prints undefined
console.log(this.attributes['joke']);
},
Now, I have read the similar question here, but I does not have sufficient reponses to explain whats going on there. Basically, I was hoping that due to this.emit(':saveState', true) the variable will persist, but it is undefined. Any ideas?
Use emit inside the end block.
res.on('end', () => {
this.emit('TellAJoke');
})
For error handling pass it on to the Unhandled or SessionEndedRequest Intents.
use emitWithState('') instead of
emit('') to move on to another Intent.
I have the following code:
app.get('/pull-requests', function (request) {
fetchRepos(fetchPullRequests);
app.on('pull-requests:fetched', function (pullRequestsByRepo) {
var html = "";
_.each(pullRequestsByRepo, function (pullRequests) {
html += 'There is <strong>'+ pullRequests.length +'</strong> pending pull request(s) for <strong>'+ pullRequests[0].title +'</strong>:';
html += '<ul>';
_.each(pullRequests, function (pullRequest) {
html += '<li><em>'+ pullRequest.title +'</em> ('+ pullRequest.url +')</li>';
});
html += '</ul>';
});
response.send(html);
});
});
It works fine once. Every second request ends raising an error Can't set headers after they are sent..
EDIT: More code to explicit the logic
function fetchRepos (callback) {
_options.path = '/orgs/'+ app.get('org') +'/repos?client_id='+ app.get('client_id') +'&client_secret='+ app.get('client_secret');
// Fetch the list of repos for a given organisation
var request = https.get(_options, function (res) {
data = "";
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
var repos = JSON.parse(data);
return callback(repos);
});
});
request.on('error', function (error) {
console.log('Problem with request: '+ e);
});
}
function fetchPullRequests (repos) {
var pullRequests = [];
_.each(repos, function (repo, index) {
_options.path = '/repos/'+ app.get('org') +'/'+ repo.name +'/pulls?client_id='+ app.get('client_id') +'&client_secret='+ app.get('client_secret');
var request = https.get(_options, function (res) {
(function () {
var data = "";
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
data = JSON.parse(data);
if (data.length > 0) {
pullRequests.push(data);
}
if (index == (repos.length - 1)) {
app.emit('pull-requests:fetched', pullRequests);
}
});
})();
});
});
}
Your problem is that whenever you call app.on('pull-requests:fetched', …), you add a new listener, meaning that when the second request arrives, it will trigger the first one again.
node then complains because you try reply twice to the first request.
You could fix your immediate issue by calling app.once, which would ensure that the only fires once, but you would still have an issue if 2 requests arrive at the same time.
The correct pattern in this case is to pass a callback to fetchRepos.
I'm relatively new to callbacks and have been unsuccessful in getting the following code to work. I have used the async.map function to return the data from each web call to its respective page. However, my console.log(return) is returning [ , undefined] even though the console.log(data) prior to the callback(data) is returning the web page's html. Here's my code:
var http = require("http"),
fs = require("fs"),
page, chap, ot,
async = require("async");
ot = fs.open('ot.txt', 'w');
page = "test";
chap = 2;
function getData(url, callback) {
var data = "";
var options = {
host: "rs.au.com",
port: 80
}
options.path = url;
console.log("request sent to: http://" + options.host + options.path);
var req = http.request(options, function(res) {
console.log("Response received " + res.statusCode);
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function(e) {
console.log(data);
callback(e, data);
});
}).end();
}
function main() {
var pathArr = [];
for ( var i = 1; i <= chap; i++ ) {
pathArr[i] = "/".concat(page, "/", i, ".html");
}
async.map(pathArr, getData, function(err, result) {
console.log("The result is :" + result);
});
}
main();
Could anyone please point out why my code is not working and how I can correct it?
Much appreciated!
EDIT: After Brandon Tilley's response I amended the callback function from callback(data) to callback(e, data), however I'm getting no response now from the last console.log output.
The Async library assumes your callbacks adhere to the standard Node.js callback signature, which is callback(err, others...). Since you are passing data as the first argument, Async assumes it's an error. You should use callback(e, data) instead (since e will be null in the case of no errors).
[Update]
The other problem is that your array is not correct. Since i starts at 1 and goes up to chap, pathArr[0] is undefined. Change:
pathArr[i] = "/".concat(page, "/", i, ".html");
to
pathArr[i-1] = "/".concat(page, "/", i, ".html");
I'm new to node.js, and I'm trying to call a service, parse its data and return it as part of a view. I can't seem to get the request to block until the response is complete. The console always logs 'wrong' before 'right' (returning the 1,2,3 array). What am I missing?
app.js
var reading = require('./reading');
app.get('/reading', function(req, res){
res.render('reading/index.stache',
{
locals : { ids : reading.list},
partials : {
list : '{{#ids}}{{.}}<br />{{/ids}}'
}
});
});
reading.js
var request,
http = require('http'),
host = 'google.com',
path ='/';
var list = function(){
var connection = http.createClient(80, host),
request = connection.request(path);
request.addListener('response', function(response){
var data = '';
response.addListener('data', function(chunk){
data += chunk;
});
response.addListener('end', function(){
console.log('right')
//var results = JSON.parse(data);
// i need results from json
return [88234,883425,234588];
});
});
request.end();
console.log('wrong');
return [1,2,3];
}
module.exports.list = list;
Of course you can't get the request to block until the response is back.
That's because there is communication latency between sending the request of and getting the response back. It would be stupid to wait and do nothing whilst that latency is happening.
Use callbacks and asynchronous control flow.
var list = function(callback){
var connection = http.createClient(80, host),
request = connection.request(path);
request.addListener('response', function(response){
var data = '';
response.addListener('data', function(chunk){
data += chunk;
});
response.addListener('end', function(){
console.log('right')
// USE A CALLBACK >:(
callback([88234,883425,234588]);
});
});
request.end();
}
If you wan't to run anything in sync have a look at the sync module. It's based on fibers.