An array[1,2,3,4]take 2 of them and send 2 requests with them;
Once completed take another 2 and create two new requests;
I know I cant do it like below because Nodejs is synchronous;
var request = require('request');
var args=[1,2,3,4];
function chunk(){...}
args = chunk(args,2); //My custom function to split array into chunks
args.forEach(function(value)
{
value.forEach(function(value_value)
{
/***********sent requests**************/
var options = {
method: 'POST',
url: 'http://dev.site/date.php',
formData: {arguments:value_value}
};
request(options, function (error, response, body)
{
if (body=='hello') {
console.log(body);
}
});
/**************************************/
});
});
please Help me
You can use request-promise and q - then chain response:
var request = require('request-promise');
var Q = require('q');
var args=[1,2,3,4];
function chunk(){...}
args = chunk(args,2); //My custom function to split array into chunks
args.forEach(function(value)
{
var result = Q();
args.forEach(function (t) {
result = result.then(request_each.bind(null, value));
});
return result; // result has the final promise (use .then on that)
});
function request_each(value) {
return Q.all(value.forEach(function(value_value)
{
/***********sent requests**************/
var options = {
method: 'POST',
url: 'http://dev.site/date.php',
formData: {arguments:value_value}
};
return request(options);
/**************************************/
}));
}
You can just use q and request (changing the request_each function):
function request_each(value) {
return Q.all(value.forEach(function(value_value)
{
var deferred = Q.defer();
/***********sent requests**************/
var options = {
method: 'POST',
url: 'http://dev.site/date.php',
formData: {arguments:value_value}
};
request(options, function (error, response, body) {
if (body=='hello') {
deferred.resolve(body);
}
});
return deferred.promise;
/**************************************/
}));
}
Related
I am trying to make a post request using NodeJS and request.
I tried using promises and the async/await like other post says but I can manage to make work.
const express = require('express');
const bodyParser = require('body-parser');
var request = require("request");
const app = express();
app.use(bodyParser.json());
var token = '';
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
function postRequest(options) {
request(options, function (error, response, body) {
if (error) throw new Error(error);
token = (JSON.parse(body)).access_token;
console.log(token + 'tet');
return (token);
});
}
async function requestToken() {
var options = {
method: 'POST',
url: 'https://simplivity#xxxx/api/oauth/token',
headers: { 'Content-Type': 'application/json' },
formData:
{
grant_type: 'password',
username: 'administrator#vsphere.local',
password: 'xxxx'
}
};
try {
var test = await postRequest(options)
return (test);
} catch (error) {
console.error(error);
}
}
var test = requestToken();
console.log(test + 'TOT');
This is the answer :
[object Promise]TOT
00bd0beb-8967-4534-8c63-2e5d0d6876d4tet
Which should be the opposite.
thank you for your help.
(async () => {
var test = await requestToken();
console.log(test + 'TOT');
})();
While not very tidy something like this should work.
Better:
requestToken()
.then(response => {
console.log(response);
});
You need to return a promise.
Change your postRequest to:
function postRequest(options) {
return new Promise(function(resolve, reject) {
request(options, function (error, response, body) {
if (error) throw new Error(error);
token = (JSON.parse(body)).access_token;
console.log(token + 'tet');
resolve(token);
});
});
}
I have using a code snippet which will return a value after post rest call to an api.
But where ever i am calling the function its not returning the value and prints undefined.
when ever i will call any where getAccessToken(), its says undefiuned, but ifi print the value am getting the output.
How do the called will get the return value, do i need to change anything in the below code.
Thanks
var getAccessToken = exports.getAccessToken = function (res) {
// body...
const request = require('request');
const authKey='EAcEa4o4SkBLo9IpZpW4Y7oDn7d6b30GlouNh28pJ6Q='
const ContentType='application/x-www-form-urlencoded' ;
var postData={
'grant_type':'client_credentials'
};
const options = {
url: 'https://xyz/v1/login',
method: 'POST',
headers: {
'Content-Type': ContentType,
'Authorization':authKey
},
body:require('querystring').stringify(postData)
};
var token;
request(options, function(errror, response, body) {
//console.log(JSON.parse(body));
token= JSON.parse(body).access_token;
});
return token;
}
Your function doesn't return anything. You may use async/await, promises or callbacks to fix it.
exports.getAccessToken = async (res) => {
...
return await request(...)
}
OR
exports.getAccessToken = function(res) {
...
return new Promise(function(resolve, reject) {
...
request(options, function(errror, response, body) {
var token = JSON.parse(body).access_token;
resolve(token);
}
});
}
// Use it like
getAccessToken().then(function(token) { ... });
OR
exports.getAccessToken = function(res, cb) {
...
request(options, function(errror, response, body) {
var token = JSON.parse(body).access_token;
cb(token);
}
}
// Use it like
getAccessToken(res, function(token) { ... });
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I have a function that returns a value which it gets from an http GET request in nodejs. How do I wait for the async request function to finish and return the result from the function that generates the request.
I have checked async library in npm, but that doesn't solve my problem.
Thanks for the help!!
function daemonGetNodeStatus(kubeURL, nodeName) {
console.log(nodeName);
var request = require("request");
var options = {
method: 'GET',
url: kubeURL+'/api/v1/nodes/'+nodeName+'/status',
headers: {
'Cache-Control': 'no-cache',
'Authorization': 'Bearer '+constants.accessToken
}
};
request(options, function(error, response, body) {
if (error)
throw new Error(error);
var bodyJSON = JSON.parse(body);
var result = [];
var temp = {};
for (var i = 0; i < bodyJSON.status.conditions.length; i++) {
if(bodyJSON.status.conditions[i].status == "True"){
result.push(bodyJSON.status.conditions[i].type);
}
}
console.log(result);
});
};
You could use a Promise.
function daemonGetNodeStatus(kubeURL, nodeName) {
console.log(nodeName);
var request = require("request");
var options = {
method: 'GET',
url: kubeURL+'/api/v1/nodes/'+nodeName+'/status',
headers: {
'Cache-Control': 'no-cache',
'Authorization': 'Bearer '+constants.accessToken
}
};
return new Promise((resolve, reject) => {
request(options, function(error, response, body) {
if (error)
reject(new Error(error));
var bodyJSON = JSON.parse(body);
var result = [];
var temp = {};
for (var i = 0; i < bodyJSON.status.conditions.length; i++) {
if(bodyJSON.status.conditions[i].status == "True") {
result.push(bodyJSON.status.conditions[i].type);
}
}
resolve(result);
});
}
daemonGetNodeStatus(url, name).then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});
function daemonGetNodeStatus(kubeURL, nodeName, callback) {
console.log(nodeName);
var request = require("request");
var options = {
method: 'GET',
url: kubeURL+'/api/v1/nodes/'+nodeName+'/status',
headers: {
'Cache-Control': 'no-cache',
'Authorization': 'Bearer '+constants.accessToken
}
};
request(options, function(error, response, body) {
if (error)
{
callback(error);
} else {
var bodyJSON = JSON.parse(body);
var result = [];
var temp = {};
for (var i = 0; i < bodyJSON.status.conditions.length; i++) {
if(bodyJSON.status.conditions[i].status == "True"){
result.push(bodyJSON.status.conditions[i].type);
}
}
callback(null, result);
}
});
}
One of the best things about Node is it's asynchronous. It might be hard to understand in the beginning, but once you know, it's the best thing. It's also the reason Node is so fast.
So, when you have to run an asynchronous function, you also send an extra function to the asynchronous function called a callback function which will be executed once the async operation is done. The above code illustrates this.
Then you can use the function like this:
daemonGetNodeStatus('http://kube.com/something', 'name', function(err, result){
if(err) {console.log(err); }
else {
console.log(result);
// do whatever you want with the async result
}
});
I'd like to answer with one more approach - async\await. If you have NodeJS v8 installed, better to stick with async\await.
Also, I made some improvements, feel free to ignore them if you don't like it.
1) async/await offers to you more convenient way to write and deal with asynchronous code. Instead of callbacks or Promise chains, you just write await.
2) Instead of iterating through array via for-loop you can use filter and map to find all the k8s conditions where status is True.
3) json field in request options will parse response as JSON and returns to you already parsed JSON value.
const request = require("request-promise");
async function daemonGetNodeStatus(kubeURL, nodeName) {
const options = {
json: true,
method: 'GET',
url: kubeURL + '/api/v1/nodes/' + nodeName + '/status',
headers: {
'Cache-Control': 'no-cache',
'Authorization': 'Bearer '+constants.accessToken
}
};
const response = await request(options);
return response.status.conditions.filter(cond => cond.status === 'True').map(cond => cond.type);
});
UPD
Any async function returns Promise, so you need to await it or call it with then\catch:
async function someAnotherAsyncFunction() {
const types = await daemonGetNodeStatus('KUBE_URL', 'NODE_NAME');
// do something with types
}
or
daemonGetNodeStatus.then(types => doSomethingWithTypes(types)).catch(error => doSomethingWithError(error));
I have for loop with a request (and another request in callback).
I have problem with memory usage (when i am go through a lot of request at same time)
here is the sample code :
var request = require('request');
for(var j=1;j<=10;j++){
request({
method: 'GET',
url: 'https://api.domain.com/items/?page='+j+'&limit=1000',
headers: {
'Content-Type': 'application/json'
}}, function (error, response, body) {
var data = JSON.parse(body)
for(var i=0;i<data.length;i++){
request({
method: 'GET',
url: 'https://api.domain.com/itemDetail/'+data[i].id,
headers: {
'Content-Type': 'application/json',
}}, function (error, response, body) {
var itemDetails = JSON.parse(body);
// save items to mongodb
}
}
});
}
The solution suggested to me it was using async module.
After reading documentation i find out eachlimit suit my needs.
The problem i have its i can use eachlimit for second loop but for first loop i dont know how use it (because first loop in not an array).
here code so far i get , and its not working:
var request = require('request');
var mongodb = require('mongodb');
var async = require('async');
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/subtitle';
for(var j=1;j<=10;j++){
request({
method: 'GET',
url: 'https://api-v2.domain.com/news/popular?page='+j+'&limit=1000',
headers: {
'Content-Type': 'application/json',
'api-version': '2',
'api-key': 'my-api-key'
}}, function (error, response, body) {
try {
var data = JSON.parse(body);
} catch (e) {
// An error has occured, handle it, by e.g. logging it
console.log(e);
}
async.each(data, function(item, callback) {
request({
method: 'GET',
url: 'https://api-v2.domain.com/news/'+item.id,
headers: {
'Content-Type': 'application/json',
'api-version': '2',
'api-key': 'my-api-key'
}}, function (error, response, body) {
// sava item in mongodb
})
callback();
}, function(err){
if( err ) {
console.log('A item failed to process');
} else {
console.log('All items have been saved successfully');
}
});
})
}
You can achieve this in a number of ways, one of them would be using whilst. With your code it'd look something like this (removed error handling and request options for readability here):
var requestCount = 0;
async.whilst(
function () {
return requestCount < 10;
},
function (firstCallback) {
request({url: "https://api-v2.domain.com/news/popular?page=" + requestCount + "&limit=1000"}, function (err1, res1, body1) {
var data = JSON.parse(body1);
async.each(
data,
function(item, secondCallback) {
request({url: "https://api-v2.domain.com/news/" + item.id}, function (err2, res2, body2) {
// sava item in mongodb
secondCallback();
});
},
function(err){
requestCount++;
firstCallback();
}
);
});
},
function (err) {
//all requests done
}
);
Once you start to nest so many callbacks, you should probably refactor this and put the second loop in it's own function. For example:
var requestCount = 0;
async.whilst(
function () {
return requestCount < 10;
},
function (callback) {
request({url: "https://api-v2.domain.com/news/popular?page=" + requestCount + "&limit=1000"}, function (err, res, body) {
var items = JSON.parse(data);
getNews(items, function(newsErr){
requestCount++;
callback(newsErr);
});
});
},
function (err) {
//all requests done
}
);
//----------------------------------------------------
function getNews(items, callback){
async.each(items, function(item, itemCallback) {
request({url: "https://api-v2.domain.com/news/" + item.id}, function (err2, res2, body2) {
// sava item in mongodb
itemCallback();
});
}, callback);
}
Also make sure to call the async callbacks within the callbacks of the request (you weren't doing it so in your code).
I'm using expressjs.
I have a router:
exports.index = function(req, res){
if(req.param('name')) {
var simpleParser = require('../tools/simpleParser');
var result = simpleParser.images(req.param('name'));
// how i can get result from simpleParser.images after it complete?
res.json(result);
}
res.render('goods');
};
An i have a simpleParser.images:
module.exports = {
images: function (url) {
if (url) {
var request = require('request'),
cheerio = require('cheerio');
request({
uri: url,
method: 'GET',
encoding: 'binary'
}, function (err, res, body) {
var tmp = [];
body = new Buffer(body, 'binary');
var $ = cheerio.load(body);
$('.products-listing li a').each(function () {
var link = $(this).find('img').attr('src');
tmp.push(link);
});
// How i can send tmp to router, when it complete?
});
}
}
};
When i asking page with ?name it return null, because request in simpleParser.images work async. How i can subscribe to result of simpleParser request function, and send json after it complete?
Like many node modules, you can provide a callback in your own utility functions. Your simpleParser.images function is not synchronous, as it uses the request module. You can have your simpleParser.images function accept a callback that will be called upon the completion of the network request and some data parsing.
var request = require('request'),
cheerio = require('cheerio');
module.exports = {
images: function (url, callback) {
if (!url) callback(null, null);
request({
uri: url,
method: 'GET',
encoding: 'binary'
}, function (err, res, body) {
if (err) callback(err);
var tmp = [];
body = new Buffer(body, 'binary');
var $ = cheerio.load(body);
$('.products-listing li a').each(function () {
var link = $(this).find('img').attr('src');
tmp.push(link);
});
// Here we have the data and can pass it in the callback
callback(null, tmp);
});
}
};
Then you essentially have your own function that can be performed asynchronously. Then in your
express route, that is async as well, so just plug in your new function
if (req.param('name'))
simpleParser.images(req.param('name'), function (err, images);
res.json(images);
});
} else {
res.render('goods');
}