I am able to set global variable but unable to get that.
pm.sendRequest(getLibraries, function (err, response) {
if(!err){
var jsonData = response.json();
console.log('Libraries: ',jsonData);
var lib_id = jsonData.contents[0].id;
console.log('Lib_id:', lib_id);
pm.globals.set("MLSLibrary_id", lib_id);
}
});
var library_id = pm.globals.get("MLSLibrary_id");
console.log('MLSLibrary_id: ', library_id);
The pm.sendRequest is asynchronous. Your request gets executed after you retrieve the global variable. If you want to execute something after the request do it in the if:
pm.sendRequest(getLibraries, function (err, response) {
if(!err){
var jsonData = response.json();
console.log('Libraries: ',jsonData);
var lib_id = jsonData.contents[0].id;
console.log('Lib_id:', lib_id);
// Execute your code with lib_id here
}
});
Related
I wrote a small module that makes a Get Request using the 'request' module. I want to do call it from another script, and use the result of the Get on the calling function like so:
var request = require('request');
function SendGet(uri) {
var outer_body = "test";
request(uri, function(error, response, body) {
console.log(body);
outer_body = body;
});
console.log(outer_body);
return outer_body;
}
exports.GetRequest = SendGet;
Then I use it like this:
var MyReq = require('./reqtest');
var uri = "http://api.myhost.com";
var result = MyReq.GetRequest(uri);
console.log("My result is:",result);
When I run it, I see in the console the body of the response when using the GetRequest but the variable that is returned still has the value used to initialize it:
c:\node messages.js
test
My result is: test
<full body here>
c:\
How can I pass back the body to the calling function?
thank you
Try this
var request = require('request');
function SendGet(uri) {
var outer_body = "test";
outer_body = request(uri, function(error, response, body) {
console.log(body);
return body;
});
console.log(outer_body);
return outer_body;
}
exports.GetRequest = SendGet;
Here you are returning the result of your callback to the variable outer_body
I'm trying to understand how to wait for http requests to finish in node. I want to make two http requests and use the results in a function that gets called after the http requests are finished.
I'm using async and request and have been using async.series as following:
var request = require("request");
var express = require('express');
var async = require("async");
app.get('/rx', function(req, res) {
var drug1 = req.query.drug1;
var drug2 = req.query.drug2;
console.log("in rx")
console.log(drug1);
console.log(drug2);
var id1 = '';
var id2 = '';
/*part of code I'm concerned with*/
async.series([
function(callback) {
id1 = getID(drug1);
console.log("function one");
console.log(id1);
callback();
},
function(callback) {
id2 = getID(drug2);
console.log("function two");
console.log(id2);
callback();
}
],
function(err, results) {
console.log(id1);
console.log(id2);
request("http://rxnav.nlm.nih.gov/REST/interaction/interaction.json?list?rxcuis=" + id1 + "&sources=" + id2, function(error, response, body) {
console.log("finished!");
res.json(body);
});
});
});
//returns an int ID
function getID(drugName) {
request("http://rxnav.nlm.nih.gov/REST/Prescribe/rxcui.json?name=" + drugName, function(error, response, body) {
var content = JSON.parse(body);
var id = parseInt(content.idGroup.rxnormId);
console.log("in getID function");
console.log(id);
return id;
});
}
The console output shows:
in rx
advil
ibuprofen
seriesone
undefined
two
undefined
undefined
undefined
finished!
GET /rx?drug1=advil&drug2=ibuprofen 304 345ms
in getID function
153010
in getID function
5640
I want to wait until each http request function is completed, and then proceed to the next portion of code. How do I achieve this?
This question (or variants thereof) has been asked more than 1000 times here on StackOverflow. Therefore I'm not going to explain it but you can search "return async" on this site (the search input at the top right corner) if you want to know more.
The basic problem is that it's impossible to return values from an async function (ever wonder why they accept callbacks?).
For your specific case, you need to change getId() to:
//returns an int ID
function getID(drugName, callback) {
request("http://rxnav.nlm.nih.gov/REST/Prescribe/rxcui.json?name=" + drugName, function(error, response, body) {
var content = JSON.parse(body);
var id = parseInt(content.idGroup.rxnormId);
console.log("in getID function");
console.log(id);
callback(null,id); // <--- this is how you return async values
});
}
Note: the null is because functions in the async.js family expects the first argument to the callback to be an error. So if there are no errors pass null. This by the way is a standard node.js practice.
Then inside async.series() you do:
async.series([
function(callback) {
getID(drug1,callback);
},
function(callback) {
getID(drug2,callback);
}
],
function(err, results) {
console.log(results[0]); // id1
console.log(results[1]); // id2
// do the rest..
});
I have var movieRecommendation which is being populated from data coming from Mongo DB. Issue is Mongoose Movie.findOne() call is asycn call which is not allowing me to get my final populated movieRecommendation which I need to send back as response.
exports.getRecommendation=function(req,res){
var movieRecommendation = [];
var id=req.params.id;
console.log('----- Get User Recommendation - ' + id);
var url = 'http://52.8.48.113:8080/recommender-server/recommender/v1/recommendations/'+id+'.do';
//make http get request
request({
url: url,
json: true
}, function (error, response, recommendations) {
// res.json(recommendations);
if (!error && response.statusCode === 200) {
recommendations.forEach(function(entry) {
**Movie.findOne({'id':parseInt(entry.itemId)},function(err, movieData){**
entry.movie = movieData;
movieRecommendation.push(entry);
//console.log('rec', movieRecommendation);
console.log(movieRecommendation.length);
});
});
}
console.log("====Final========"+movieRecommendation.length);
//Output = 0
});
res.json(movieRecommendation); // Here movieRecommendation is coming as black Array
};
Please let me know how I can get finally populated movieRecommendation var at end to make it available for response.
For this type of issues we can use Async library. To populate the data finally once all the operations done, we can use async.each collection from Async Library.
For example:
NOTE:Install Async by this command
npm install async to use async library
var async = require("async");
var recomenmendations = [{"data2" : "value2"} , {"data1" : "value2"}, {"data3" : "value3"}, {"data4" : "value4"} ]
var movieRecommendation = [];
async.each(recomenmendations,
function(recomenmendationItem, callback){
console.log("Here you can query the required data using current recomenmendations ITEM");
console.log(recomenmendationItem);
callback();
// Movie.find({'id':parseInt(recomenmendationItem.itemId)},function(err, movieData){
// recomenmendationItem.movie = movieData;
// movieRecommendation.push(entry);
// callback();
// });
},
function(err){
console.log("here you can send your resopnse");
console.log("This section will be executed once all the recomenmendations are processed");
//res.json(movieRecommendation)
}
);
You can query the mongoDB as shown with comment section. You should use callback() once all the operations performed for an iteration.
As I mentioned in one of my comments, use the callback passed to the iterator function and call it inside the Movie.findOne() callback. That way, async.each will know when each step has finished:
async.each(recomendations, function (recomendationItem, callback) {
Movie.findOne({'id':parseInt(entry.itemId)},function(err, movieData){
if (err) return callback(err); // if you have an error on you search, just pass it to the iterator callback
recommendationItem.movie = movieData;
movieRecommendation.push(recommendationItem);
callback();
});
}, function (error) {
if (error) return res.json ({ error: error }); // you should also check if an error ocurred
res.json(movieRecomendation);
});
Just to point out: you can also use async.eachSeries, that will just call the next step of your iteration when the previous one has returned (if that matters to you, but I think it's not your case though) and it has the same signature.
#Vivek Panday replace the following code inside your exports.getRecommendation function to get your expected output. We don't need to use the count variable if we use the callback function. And an important thing is we have to use callback(); once all the process done. I think you have not used callback function properly in The example you have worked out. Use the following code If there is any issue please let me know.
var async = require('async');
var request = require("request");
var movieRecommendation = [];
var id=req.params.id;
console.log('----- Get User Recommendation - ' + id);
var url = 'http://52.8.48.113:8080/recommender-server/recommender/v1/recommendations/'+id+'.do';
//make http get request
request({
url: url,
json: true
}, function (error, response, recommendations) {
if (!error && response.statusCode === 200) {
console.log('recommendation lenght '+ recommendations.length);
async.each(recommendations,
function(recommendationItem, callback){
Movie.findOne({'id':parseInt(recommendationItem.itemId)},function(err, movieData){
recommendationItem.movie = movieData;
movieRecommendation.push(recommendationItem);
//you have to use callback(); once all your process is done
callback();
});
},
function(err){
//you should use this function, this will be execute once all the process done
console.log(movieRecommendation);
console.log("finally callback");
res.json(movieRecommendation);
}
);
}
});
I have tried as per given suggestion above ..
var async = require("async");
var recomenmendations = [{"data2" : "value2"} , {"data1" : "value2"}, {"data3" : "value3"}, {"data4" : "value4"} ]
var movieRecommendation = [];
async.each(recomenmendations,
function(recomenmendationItem, callback){
console.log("Here you can query the required data using current recomenmendations ITEM");
console.log(recomenmendationItem);
// Movie.find({'id':parseInt(recomenmendationItem.itemId)},function(err, movieData){
recomenmendationItem.movie = movieData;
movieRecommendation.push(entry);
console.log("any data"); // line y
});
callback();
},
function(err){
console.log("here you can send your resopnse"); // line x
console.log("This section will be executed once all the
recomenmendations are processed");
//res.json(movieRecommendation)
}
);
But still face same issue line x is printing before line y ,which is making again same issue.
However I have tried something given below and achieved expected result .
exports.getRecommendation=function(req,res){
var movieRecommendation = [];
var id=req.params.id;
console.log('----- Get User Recommendation - ' + id);
var url = 'http://52.8.48.113:8080/recommender-server/recommender/v1/recommendations/'+id+'.do';
//make http get request
request({
url: url,
json: true
}, function (error, response, recommendations) {
// res.json(recommendations);
if (!error && response.statusCode === 200) {
console.log('recommendation lenght '+ recommendations.length);
// recommendations.forEach(function(entry) {
var count=0;
async.each(recommendations,function(recommendationItem){
// console.log(recommendationItem);
Movie.findOne({'id':parseInt(recommendationItem.itemId)},function(err, movieData){
recommendationItem.movie = movieData;
movieRecommendation.push(recommendationItem);
count ++;
console.log('final res length : ' + movieRecommendation.length);
console.log('final res length count : ' + count +' and item recomm lenght ' + recommendations.length );
if(count === recommendations.length){
console.log(' =====Final=====> here you can send your response =========' + movieRecommendation.length);
res.json(movieRecommendation);
}
});
// callback();
});
}
});
};
Still I am open for any feedback and suggestions.
I have an http server with a handleRequest callback that runs another script in vm.runInNewContext for each request. The script that runs inside vm.runInNewContext makes some asynchronous http post requests and writes the server response only after getting the responses from the posts.
As a result, the code of handleRequest callback ends before the server response is written.
Is it safe? or is there a way to avoid this situation?
Here is some code:
var server = http.createServer(handleRequest);
server.listen(8080);
var handleRequest = function (request, response) {
// get request data...
var context = {
ServerRequest : request,
ServerResponse : response
};
var stringScript = // a string with the script that posts data
var script = vm.createScript(stringScript);
script.runInNewContext({ context: context });
}
the script string does this:
var request = require('request');
var options = {....}
var req = request.get(options);
req.on('response', function (res) {
var chunks = [];
res.on('data', function(chunk) {
chunks.push(chunk);
});
res.on('end', function() {
var buffer = Buffer.concat(chunks);
var encoding = res.headers['content-encoding'];
if (encoding == 'gzip') {
zlib.gunzip(buffer, function(err, decoded) {
// set response headers and write the response
context.ServerResponse.end(decoded.toString());
});
} else if (encoding == 'deflate') {
zlib.inflate(buffer, function(err, decoded) {
// set response headers and write the response
context.ServerResponse.end(decoded.toString());
})
} else {
// set response headers and write the response
context.ServerResponse.end(buffer.toString());
}
});
});
Simple solution: Return a promise (e.g. use the Q-library) from the VM-script.
script.runInNewContext will return whatever you return from the VM-script. That way you have a "callback" for when the VM code finishes.
// Script for VM
// I simplified it. Just resolve or reject the promise whenever you are done with your work
'use strict';
var defer = q.defer();
doABarrelRoll(function() {
defer.resolve('RESULT');
});
defer.promise; // This line will return the promise.
When returning a value from a VM-script, you do not need any return construction. Just write the thing you want and let the magic happen.
// Script for current context
'use strict';
var server = http.createServer(handleRequest);
server.listen(8080);
var handleRequest = function (request, response) {
// get request data...
var context = {
ServerRequest : request,
ServerResponse : response
};
var stringScript = // a string with the script that posts data
var script = vm.createScript(stringScript);
var prom = script.runInNewContext({
context: context,
q: require('q'),
});
prom.done(function ($result) {
console.log('VM finished with result: ' + $result);
});
}
How do I set a variable to a query? I am trying to use functions and callbacks in node.js to work through async, but I am not sure how to get a query to equal to a variable. What I am trying to do in this code is take a friend collection that belongs to a user and return the friends result(which I don't think I am doing correctly in the query insertAll) and then find the user's info for each of the query. And then return the results as a render. I am not sure how to call render either with this...
Here is my code:
exports.contactList = function(req, res) {
var insertFriend = function(data, callback) {
var friend = User.findById({_id: user.friendStatus.fuId}, function() {
callback(null, data);
}, friend);
};;
var insertAll = function(coll, callback) {
var queue = coll.slice(0),
friendX;
(function iterate(){
if(queue.length === 0) {
callback();
return;
}
friendX = queue.splice(0,1)[0];
insertFriend(friendX, function(err, friendX) {
if(err) {throw err;}
console.log(friendX + ' inserted');
process.nextTick(iterate);
});
})();
};
insertAll([Friend.findOne({userId: req.signedCookies.userid})], function(){
});
};
A Query object is returned if you do not pass a callback.
From http://mongoosejs.com/docs/queries.html:
When a callback function:
is passed, the operation will be executed immediately with the results passed to the
callback.
is not passed, an instance of Query is returned, which provides a special QueryBuilder
interface for you.