MeteorJS: Can not assign a variable - javascript

I have such code, and want to assign one variable to another in function, code example:
Meteor.methods({
parsing:function(){
var aa ;
request("https://google.com/", function(error, response, body) {
if (!error && response.statusCode == 200) {
var k=1;
aa = k;
}
});
console.log(aa);
}
});
It's loged undefined, can someone explain me why ?
EDIT :
Meteor.methods({
parsing:function(){
var aa ;
var tmp;
request("https://google.com/", function(error, response, body) {
if (!error && response.statusCode == 200) {
var k=1;
aa = k;
console.log(aa);
request("https://google.com/xyz", function(error, response, body) {
tmp = response.request.uri.href;
});
}
console.log(tmp);
});
}
});
For example i need console.log(tmp); only when my second request will be call (ended)

The function that you give as parameter of request will only be executed when the request will have an answer from Google. But the next part of the code (your console.log line) is still executed without waiting anything.
If you want to wait the request result before your log, add it to your function:
parsing:function(){
var aa ;
request("https://google.com/", function(error, response, body) {
if (!error && response.statusCode == 200) {
var k=1;
aa = k;
console.log(aa);
}
});
}
EDIT :
Well, you can use the same technique as many times you want:
parsing:function(){
var aa ;
var tmp;
request("https://google.com/", function(error, response, body) {
if (!error && response.statusCode == 200) {
var k=1;
aa = k;
console.log(aa); // Waited the first answer.
request("https://google.com/xyz", function(error, response, body) {
tmp = response.request.uri.href;
console.log(tmp); // Waited the second one.
});
}
});
}

Related

Why is my function turning into a object?

I have several ajax requests in my project so to simplify my code i created a function to handle the requests.
I am passing a success function to load when status is == 200 however even though the data is being sent correctly i am receiving "uncaught type error success is not a function" error. Using typeof i can see success starts as a function but then displays as an object.
here is my code
//function to handle ajax requests
function sendRequest(link, requestType, success, data) {
var request = new XMLHttpRequest(),
url = link;
request.open(requestType, url, true);
request.onload = function () {
if (request.status >= 200 && request.status < 400) {
console.log("success");
var responseText = request.responseText;
console.log(typeof(success));
success(responseText);
} else {
consoloe.log("error");
}
}
request.send(data);
}
//calling function passing success function as argument
var jsonText = "json.php";
sendRequest(jsonText, 'GET', function (response) {
var json = JSON.parse(response),
postcodesArray = [],
jsonLength = json.length,
i;
for (i = 0; i < jsonLength; i++) {
postcodesArray.push(json[i].from_postcode);
}
var postcodes = postcodesArray.filter(Boolean),
pstcodeLength = postcodes.length,
n;
for (n = 0; n < pstcodeLength; n++) {
geocodeAddress(postcodes[n]);
}
});
//EDIT fiddle containing all my code
https://jsfiddle.net/x1qe73s8/
Reading your jsfiddle, your code is probably going through the sendLatLng function where you have
sendRequest(url, 'POST', null, data);
typeof null is "object".

How to pass the value of the request.get to the callback using async.series node.js

I wanna show my code:
request({url: API_URL}, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log("Items received with success.");
var data = JSON.parse(body);
// catch duration from video
for(var list in data) {
var item = data[list];
async.series([
function(callback){
console.log("I'm inside fileExists function");
var result = '';
request.get('http://tobeymotos.com.br/video.mp4', function (error, response, body) {
if (!error && response.statusCode == 200) {
var video = body;
console.log("File exists and is OK");
var result = true;
console.log("Valor da result", result);
}
else{
console.log("This file do not exists, check error: "+ error);
var result = "xixi";
}
});
// usar aqui
callback(null, result);
},
function(callback){
// catch video duration
file = "http://tobeymotos.com.br/video.mp4"; // used as e.g.
console.log("I'm inside getVideoDuration function");
getDuration(file).then(function (duration) {
console.log("Duração do vídeo: " +duration);
return duration;
});
callback(null, 'b');
},
function(callback){
// code c
callback(null, 'c');
},
function(callback){
// code d
callback(null, 'd');
}],
// optional callback
function(err, results){
console.log(results);
}
)
return 0;
}
} else {
console.log("Error: "+error);
}
});
I'm using async.series to perform some functions in sequence, because I depend on the result of the first one, to continue with the next.
As you can see I have a "request.get" in the first function, where:
request.get('http://tobeymotos.com.br/video.mp4', function (error, response, body) {
if (!error && response.statusCode == 200) {
var video = body;
console.log("File exists and is OK");
var result = true;
console.log("Valor da result", result);
}
else{
console.log("This file do not exists, check error: "+ error);
var result = "xixi";
}
});
// usar aqui
callback(null, result);
The problem is that I can not call result in the callback, it just does not "exit" the request.get
Some help?
request({url: API_URL}, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log("Items received with success.");
var data = JSON.parse(body);
// catch duration from video
for(var list in data) {
var item = data[list];
async.series([
function(callback){
console.log("I'm inside fileExists function");
var result = '';
request.get('http://tobeymotos.com.br/video.mp4', function (error, response, body) {
if (!error && response.statusCode == 200) {
var video = body;
console.log("File exists and is OK");
var result = true;
console.log("Valor da result", result);
callback(null, result);
}
else{
console.log("This file do not exists, check error: "+ error);
var result = "xixi";
callback(null, result);
}
});
// usar aqui
},
function(callback){
// catch video duration
file = "http://tobeymotos.com.br/video.mp4"; // used as e.g.
console.log("I'm inside getVideoDuration function");
getDuration(file).then(function (duration) {
console.log("Duração do vídeo: " +duration);
return duration;
});
callback(null, 'b');
},
function(callback){
// code c
callback(null, 'c');
},
function(callback){
// code d
callback(null, 'd');
}],
// optional callback
function(err, results){
console.log(results);
}
)
return 0;
}
} else {
console.log("Error: "+error);
}
});
Your callback is outside of the request.get function, this is possibly causing your callback to call before the request has returned due to the nature of Node JS. Node JS is non-blocking and so does not wait for a function to be carried out before moving on to the next unless explicitly told to. Putting the callback inside of the request.get response function will force it to wait for the request to return and then carry out the callback with the result

Make GET request inside for loop

My code:
var locations = {"testurl1", "testurl2"}, results = [];
locations.forEach(function(location,index){
request.get(location,function (error, response, body){
if (!error && response.statusCode == 200) {
var jsonResponse = JSON.parse(body);
results.add(jsonResponse.address);
}
}
})
console.log(results);
The results are printed as blank due to asynchronous get request. How can i make this work so I have all addresses in results?
After each response, check if it was the last one.
var locations = {"testurl1", "testurl2"}, results = [];
locations.forEach(function(location,index){
request.get(location,function (error, response, body){
if (!error && response.statusCode == 200) {
var jsonResponse = JSON.parse(body);
results.add(jsonResponse.address);
console.log('Address received: ' + jsonResponse.address);
if (results.length == locations.length) {
console.log('All addresses received');
console.log(results);
}
}
}
})
You also may want to have some timeout, so you can show a response if it takes too long. Also, a request may fail, in which case it won't be added to result, so you can keep a separate counter to check for that. A bit rough, but something like this:
var locations = {"testurl1", "testurl2"}, results = [];
var failedCount = 0;
locations.forEach(function(location,index){
request.get(location,function (error, response, body){
if (!error && response.statusCode == 200) {
var jsonResponse = JSON.parse(body);
results.add(jsonResponse.address);
console.log('Address received: ' + jsonResponse.address);
} else {
// Keep a counter if a request fails.
failedCount++;
}
// Success + failed == total
if (results.length + failedCount == locations.length) {
console.log('Addresses received. ' + failedCount + ' requests have failed');
console.log(results);
}
});
});
// Set a timer to check if everything is fetched in X seconds.
setTimeout(function(){
if (results.length + failedCount < locations.length) {
console.log('10 seconds have passed and responses are still not complete.');
}
}, 10000);
Maybe promises can help in this situation. Here is my solution:
'use strict';
var request = require('request');
var Q = require('q');
var defer = Q.defer();
var promise = defer.promise;
var locations = [
'http://www.google.com', 'http://www.instagram.com'
],
results = [];
locations.forEach(function(location, index) {
request.get(location, function(error, response, body) {
if (!error && parseInt(response.statusCode) === 200) {
results.push(response.statusCode);
}
if ((locations.length - 1) === index) {
defer.resolve();
}
});
});
promise.then(function() {
console.log('RESULTS:', results);
});
I tested this and it's working fine. Promises are briefly explained here.

Node.js : multiple callbacks from one function

I've run into a problem in my application's code and I would like to know the best way to handle it: I have a function that applies 5 values on callback and I would like to know the best way to use it.
Here is my function code :
var someFunc = function(callback) {
var http = require('http');
var id;
var url = 'http://somesite.com/json';
// First request to get an array of 5 elements
http.get(url, function(res) {
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
var jsonResult = JSON.parse(body);
// 5 requests with a value from each of the 5 elements
for (var i=0;i<5;i++)
{
(function(idx) {
gameId = jsonResult.gameList[idx].id;
url = 'http://somesite.com' + id + '/token';
http.get(url, function(res) {
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
jsonRes = JSON.parse(body);
callback.apply(null, [idx, jsonRes.interestScore]);
});
}).on('error', function(e) {
console.log("Got error: ", e);
});
})(i);
}
});
}).on('error', function(e) {
console.log("Got error: ", e);
});
};
exports.someFunc = someFunc;
When I call the function to retrieve the 5 values I do it like this :
exports.featured = function(req, res){
getSome.someFunc(function callback(result) {
var variables = {};
var variableName = result;
variables[variableName] = jsonRes.interestScore;
res.render('featured', { score0: variables[0], score1: variables[1], score2: variables[2], score3: variables[3], score4: variables[4] });
});
};
Unfortunately 'res.render' is called after the function retrieved only 1 value, so I want to know how to do it proprely, or make a proper callback.
Thanks.
The function you call is async, response end events can be happening anytime. And your code causes res.render to execute 5 times, but you only need it to execute 1 time with 5 values. You should be using a module like async which will help you to fire multiple tasks, and callback when all of them is finished.
Example:
var jsonResult = JSON.parse(body);
var arr = [];
for(var i = 0; i < 5; i++){
arr.push(jsonResult[0].interestScore);
}
async.map(arr, myAsyncFunction, function(err, results){
// results[0] => response of first index
// results[4] => response of last index
});
The first problem which I'm seeing is that you are assigning listener for the end event five times. You should do that only once. You can collect the result five times and after that call the callback. Here is an example which uses request module:
var request = require('request');
var makeRequests = function(callback) {
var result = [],
done = 0;
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
// read the body here
var searchFor = [
'nodejs', // 1
'http request', // 2
'npm', // 3
'express', // 4
'javascript' // 5
];
for(var i=0; keyword = searchFor[i]; i++) {
request('https://www.google.bg/search?q=' + keyword, function (error, response, body) {
if (!error && response.statusCode == 200) {
result.push(body);
++done;
if(done == searchFor.length) {
callback(result);
}
}
});
}
}
});
}
makeRequests(function(result) {
console.log("result=" + result.length);
})

Making the while loop synchronous

I've got a following piece of code
var page = 2;
var last_page = 100;
while(page <= last_page) {
request("http://some_json_server.com/data?page=" + page, function (error, response, body) {
if (!error && response.statusCode == 200) {
store_data(body)
}
page++;
});
}
I've done the following, but it is actually not retrieving anything. Am I doing this correctly?
var page = 2;
var last_page = 100;
while(page <= last_page) {
var async_arr = [];
async_arr.push(
function(next) {
request("http://some_api_url?page=" + page, function (error, response, body) {
if (!error && response.statusCode == 200) {
store_data(body);
}
});
}
);
async.series(
async_arr, done
);
With while you get a busy loop, which is counter-purpose in Node.
Make it a recursive function instead. Each call will be done in a separate tick.
var page = 2;
var last_page = 100;
(function loop() {
if (page <= last_page) {
request("/data?page=" + page, function (error, response, body) {
if (!error && response.statusCode == 200) {
store_data(body)
}
page++;
loop();
});
}
}());
You're looking for async.whilst(). This solution is assuming you actually want to do each request after the other. As #UpTheCreek mentions (edit: the comment I referred to was edited) it would likely be possible to do it asynchronously and keep track of each result using async.parallel.
var page = 2,
lastPage = 100;
async.whilst(function () {
return page <= lastPage;
},
function (next) {
request("http://some_json_server.com/data?page=" + page, function (error, response, body) {
if (!error && response.statusCode == 200) {
store_data(body)
}
page++;
next();
});
},
function (err) {
// All things are done!
});
You can also wrap your while loop in async and break after your promise resolves/conditions have been met...
const request = require("request")
;(async()=>{
let results = []
while(true){
await new Promise(resolve => {
request('http://www.seanbehan.com/', (err, resp, body)=>{
console.log(new Date, 'Downloading..')
results.push(body)
resolve(body)
})
})
if(results.length >= 5){
break
}
}
console.log(results)
})()

Categories