Wait for API call before proceeding in NodeJS - javascript

I have a problem with async and await, here I am trying to get te weather from a weather API but in my main function getWeather I want the code to wait for my http.get to be done before proceeding. At the moment, as you can imagine, the output on console is first "test" then "In London temperature is ...". I tried quite a lot of different ways of using promises and async/await but none of them work...
Does someone know how to get the weather printed first and then "test"? Thx
var http = require('http');
function printMessage(city, temperature, conditions){
var outputMessage = "In "+ city.split(',')[0] +", temperature is
"+temperature+"°C with "+conditions;
console.log(outputMessage);
}
function printError(error){
console.error(error.message);
}
function getWeather(city){
var request = http.get("http://api.openweathermap.org/data/2.5/weather?q="+ city +"&APPID=[API_ID]&units=metric", function(response){
var body = "";
response.on('data', function(chunk){
body += chunk;
});
response.on('end', function(){
if (response.statusCode === 200){
try{
var data_weather = JSON.parse(body);
printMessage(city, data_weather.main.temp, data_weather.weather[0].description);
} catch(error) {
console.error(error.message);
}
} else {
printError({message: "ERROR status != 200"});
}
});
});
console.log('test');
}
getWeather("London");

Wrap request in a Promise:
function requestAsync() {
return new Promise((resolver, reject) => {
// request
http.get("http://api.openweathermap.org/data/2.5/weather?q=" + city + "&APPID=[API_ID]&units=metric", function (response) {
var body = "";
response.on('data', function (chunk) {
body += chunk;
});
response.on('end', function () {
if (response.statusCode === 200) {
try {
var data_weather = JSON.parse(body);
printMessage(city, data_weather.main.temp, data_weather.weather[0].description);
// request will done here!
resolver();
return;
} catch (error) {
console.error(error.message);
}
} else {
printError({ message: "ERROR status != 200" });
}
// request was failed!
reject();
});
});
})
}
and using async/await to call requestAsync:
async function getWeather(city) {
await requestAsync();
console.log('test');
}
getWeather("London");

Try this:
getWeather = function(city){
return new Promise(async function(resolve, reject){
try{
var dataUrl = await http.get("http://api.openweathermap.org/data/2.5/weather?q="+ city +"&APPID=[API_ID]&units=metric";
resolve(dataUrl);
} catch(error) {
return reject(error);
}
})
};

Related

using try-catch for https but don't catch any error

am using HTTPS to fetch data from a website, what I want to do is to catch any error that could happen,
but the thing is that it catches nothing so this is my main code
test = async() => {
console.log("Hellow")
now = new Date();
const https = require("https");
https.get("website",{ agent: proxyy },
(res) => {
var body = "";
res.on("data", function (chunk) {
body += chunk;
});
res.on("end", function () {
var resp = JSON.parse(body);
data_wanted = resp.data
const desiredItem = data_wanted.find((item) =>
item.name.includes("data")
);
console.log(desiredItem)
});
}
);
};
I tried multiple ways for the error catch like this
async function run() {
try {
await test();
} catch (error) {
console.log(error)
}
and also this way
async function f() {
try{
run = await test()
}catch(e){
console.log("Hello world")
}
}
it tried using the try-catch inside the function but also didn't works, my best guess that the try-catch is being executed before the function finish fetching
EDIT 1: so my real intention is to do a while loop which keep trying until there is not error
const https = require('https');
https.get('https://encrypted.google.com/', (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
}).on('error', (e) => {
console.error(e);
});
https://nodejs.org/api/https.html#https_https_get_options_callback

How can I run several async api functions, then call another function when all are complete?

I'm using a node script to make several api calls asynchronously and now i need to 'do something' once those calls are done. Not sure what to do in my createProject() function after i perform the request, set the options and get doSomething AFTER the options are set.
function performRequest(reqOptions, reqBody, success) {
const req = https.request(reqOptions, (res) => {
var chunks= [];
// data received
res.on('data', function (chunk) {...});
// data processed
res.on('end', function() { success(Buffer.concat(chunks).toString()); });
});
// error occurred during request
req.on('error', (e) => {
console.error('Request error: ' + e);
});
req.write(JSON.stringify(reqBody));
// end request
req.end();
}
function createProject(name) {
var reqOptions = {...};
var reqBody = {...};
performRequest(reqOptions , reqBody , function(data) {
// project successfully created - set project options
setOption1(data.id);
setOption2(data.id);
// after options set, do something
doSomething();
});
}
function setOption1(id) {
// performRequest(...)
}
function setOption2(id) {
// performRequest(...)
}
function doSomething() { ... }
We can make non-bloking function to blocking function using Promise, await, async
function performRequest(reqOptions, reqBody, success) {
return new Promise((resolve, reject) => {
const req = https.request(reqOptions, (res) => {
var chunks = [];
// data received
res.on('data', function (chunk) { });
// data processed
res.on('end', function () {
resolve(Buffer.concat(chunks).toString());
});
})
// error occurred during request
req.on('error', (e) => {
console.error('Request error: ' + e);
reject(e);
});
req.write(JSON.stringify(reqBody));
// end request
req.end();
});
}
async function createProject(name) {
var reqOptions = { ... };
var reqBody = { ... };
var data = await performRequest(reqOptions, reqBody);
// project successfully created - set project options
await setOption1(data.id);
await setOption2(data.id);
// after options set, do something
doSomething();
}
async function setOption1(id) {
return performRequest(...)
}
async function setOption2(id) {
return performRequest(...)
}
function doSomething() {
}

Parse Cloud Code - Await and return relation query

so I'm trying to get this cloud query function to run. Basically, I would like to get return the profile by its ID. Then using that result object, run a relation query and return the first result.
I'm not sure if I'm getting mixed up but I'm struggling on awaiting for the full query to finish before returning.
Thanks
Parse.Cloud.define("getLastWeightForAnimal", async (request) => {
try {
var AnimalProfiles = Parse.Object.extend("animal_profiles");
var query = new Parse.Query(AnimalProfiles);
query.get(request.params.id).then((animalProfile) => {
var AnimalWeights = animalProfile.relation("weights").query();
AnimalWeights.descending("createdAt");
let result = await AnimalWeights.first();
return result;
}, (error) => {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
console.log("Uh Oh Inner");
console.log("Error Inner: "+ error);
});
} catch (e) {
console.log("Uh Oh");
console.log("Error: "+ e);
}
});
If you return inside of a promise .then(function(){return 'a'}) thereturn 'a'does not return theasync (request)` !
If you do
Promise.resolve()
.then(function(){return 'a'}) // this 'a' does not go to any parent function!
.then(function(val){console.log(val)}) // it goes here!
you would see 'a' in your log, as a simple illustration.
You can switch it to async/await
Parse.Cloud.define("getLastWeightForAnimal", async (request) => {
try {
var AnimalProfiles = Parse.Object.extend("animal_profiles");
var query = new Parse.Query(AnimalProfiles);
var animalProfile = await query.get(request.params.id)
var AnimalWeights = animalProfile.relation("weights").query();
AnimalWeights.descending("createdAt");
let result = await AnimalWeights.first();
return result;
} catch (e) {
console.log("Uh Oh");
console.log("Error: "+ e);
}
});
OR simply return the promise, which since you're using async will automatically return the value of the promise.
Parse.Cloud.define("getLastWeightForAnimal", async (request) => {
try {
var AnimalProfiles = Parse.Object.extend("animal_profiles");
var query = new Parse.Query(AnimalProfiles);
// note new return!!
return query.get(request.params.id).then((animalProfile) => {
var AnimalWeights = animalProfile.relation("weights").query();
AnimalWeights.descending("createdAt");
let result = await AnimalWeights.first();
return result;
}, (error) => {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
console.log("Uh Oh Inner");
console.log("Error Inner: "+ error);
});
} catch (e) {
console.log("Uh Oh");
console.log("Error: "+ e);
}
});

Promise returns wrong value

In my code I try to assign a value to json variable to return it after (because I can't return it from the anon. function).
As my function is async, because it sends requests (maybe someone knows how to make it sync? I didn't plan to make it asynchronous), I've added await before the request (https.get).
I've been trying to get value from the Promise, but it's always undefined, even though I've awaited the async function.
Here's a code:
async function get_users() {
const https = require('https');
var token = '...';
var json = undefined;
await https.get('...', (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
json = JSON.parse(data)['response']['items'];
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
return json;
}
get_users().then(function(result) {
console.log(result);
});
Return a Promise and resolve it, when the end event is called, otherwise reject it in case of an error occurred:
async function get_users() {
const https = require('https');
const token = '...';
return new Promise((resolve, reject) => {
https.get('...', resp => {
let data = '';
resp.on('data', chunk => {
data += chunk;
});
resp.on('end', () => {
let json;
try {
json = JSON.parse(data)['response']['items'];
} catch (e) {
reject(e);
};
resolve(json);
});
}).on("error", err => reject(err));
});
}
get_users().then(result => console.log(result));
Please refer my below code.I had issues with getting responses from Promises too.But i finally got it to work.Here's the code:
var output;
var rp = require('request-promise-native');
var myJSONObject = {
"inputs": [{
"name": "<name>",
"value": < value >
}]
};
var orchName = 'TEST05';
postData = JSON.stringify(myJSONObject);
return networkCall(postData, orchName).then((response) => {
console.log('response is' + response)
}).catch((response) => {
console.log(`ERROR: ` + response);
});
function networkCall(postData, orchName) {
return new Promise((resolve, reject) => {
var options = {
method: 'post',
uri: '<URL>',
body: postData,
auth: {
'user': 'usr',
'pass': 'pwd'
},
json: true
};
return rp(options)
.then(body => {
var response = body;
resolve(response);
})
.catch(err => {
console.log('FAILED' + err);
reject(err);
});
});
}
This way your code can run in Synchronous Flow.If the return value is undefined,then,what might have probably happened is that the calling function would have finished executing even before the called function returns its response.But the above approach would work just fine.

Use result of HTTPS GET request [Node.js] [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I'm stuck with a small problem I think, but I can't find a way to solve it.
I want to load a remote JSON in a variable, using Node.js HTTPS GET request. It's a success, but I can't use it anywhere else in my code. My function is the following (from Node.js doc):
function getMyFile() {
var https = require('https');
https.get('URL_I_am_targeting/file.json', (res) => {
var { statusCode } = res;
var contentType = res.headers['content-type'];
let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
// consume response data to free up memory
res.resume();
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => {
rawData += chunk;
});
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
console.log(parsedData);
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
}
The request works fine, as I am able to log my .json in the console correctly. But my problem is that I can't use the constant "parsedData" anywhere else in my code. I tried to write my
return parsedData;
at several places in my function, but when I use the function in my code and try f. e.
var fileContent = getMyFile();
console.log(fileContent);
fileContent is undefined. It's like parsedData can't go out of the request. There is no error logged, the request goes fine, but I just can't use the content out of it.
I am not a Javascript professional, and it's probably something I get wrong with returning value from this request.
If somebody knows where I'm wrong and what could do the trick, it will be greatly appreciated !
Thanks !
You could write a promise-based wrapper for your function:
function getMyFile() {
var https = require('https');
return new Promise((resolve, reject) => {
https.get('URL_I_am_targeting/file.json', (res) => {
var { statusCode } = res;
var contentType = res.headers['content-type'];
let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
// consume response data to free up memory
res.resume();
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => {
rawData += chunk;
});
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
resolve(parsedData);
} catch (e) {
reject(e.message);
}
});
}).on('error', (e) => {
reject(`Got error: ${e.message}`);
});
});
}
So that, you can use the function like this:
getMyFile()
.then(response => {
// handle success response here
})
.catch(error => {
// handle error here
});
function getMyFile() {
return new Promise((resolve,reject)=>{
//your logic and data manipulations here and finally resolve the variable
resolve(parsedData)
})
}
call it like this
getMyFile().then((parsedData)=>{
//parsedData is the returned value u needed
}).catch((error)=>{
//if any error handle it
})

Categories