JS Function executing too fast - javascript

I'm doing a JSON call like this:
var desc = getItemDescriptions(xxx);
function getItemDescriptions(xxx) {
var url = "xxx;
var info = {};
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
info ["..."] = body.result[xxx].yyy;
info ["..."] = body.result[xxx].yyy;
info ["..."] = body.result[xxx].yyy;
info ["..."] = body.result[xxx].yyy;
info ["..."] = body.result[xxx].yyy;
}
})
return info;
}
My Problem is, the JSON request need some time to get response back... and my function doesn't wait for this response. The Function returns the empty array without waiting.
How can i wait for response and then return the filled array?
thx

Its not like executing fast, it is the way javascript runs statement after statement. To get the data you need to do that in success callback function, the data would be available only when the server response comes back as its asynchronous call by the time response comes your javascript executes next statements.

Juhana already linked to you the best place to get a good solution. How to return the response from an async call
A quick and dirty hack would be (if request is a jQuery-like Ajax-function) to make the request synchronus.
This might be done by adding async: false to the first parameter passed to request:
request({ url: url,json: true, async: false}, function ....
That way return info will be executed AFTER your request has finished.
HTH
Georg

Related

I can't seem to break out of A $.each() loop

I can't seem to manage to break out of my each loop if the ajax returns an error. I've tried
return false;
and other similar thing but the $.each still continues to run.
I need to be able to do this so that I can display error messages from my back end after posting it via ajax(I know this is bad practice however a client needed to be able to be able to send multiple forms off at once.).
Can anyone explain what I've done wrong?
var postAll = function(button_clicked)
{
e.preventDefault();
var form_response = [];
var formsCollection = document.getElementsByTagName("form");
$.each(formsCollection, function (key, value)
{
console.log(value.action);
console.log(value.id);
var url = value.action;
var id = value.id;
var data = ($('#' + id + '').serialize());
if (id == 'additionalInfo')
{
data = {'Add_info': $('#Add_info').val(),};
}
if (id != 'DONE')
{
$.ajax({
type: "POST",
dataType: 'json',
url: url,
beforeSend: function (xhr)
{
xhr.setRequestHeader('X-CSRF-TOKEN',$("#token").attr('content'));
},
data: data,
success: function (data)
{
console.log('success'); // show response from the php script.
form_response.push(data); // show response from the php script.
},
error: function (data)
{
console.log('fail'); // show response from the php script.
display_errors(data, id); // show response from the php script.
return true;
}
});
}
});
}
AJAX is asynchronous, when executing your $.each function it will execute the AJAX call and "Not wait" for the others to finish
To solve your problem you'll have to write a function that will execute the first ajax call and in the success it will execute itself again with the second ajax call.
Example:
var data = [form1,form2...etc];
function letsLoop(data,index = 0){
$.ajax({
url:....
success: function(){
letsLoop(data,index+1);
},
error: function(){
}
});
}
and here you call your function:
letsLoop(data,0);
If by breaking out of the loop you mean the return in your error handler, then it won't work as you think it would.
Your loop creates asynchronous requests 'at once'. Then each of these requests is handled by the browser (more or less simultaneously), then come responses. So by the time your error handler runs the loop has long finished.
BTW, the return in your case relates to the error handler, not the function inside the loop.
So, to achieve what you want you should 'queue' your AJAX requests and perform them one by one.
One possible solution is to create an array of forms then take (and remove it from the array) the first one, perform a request, on a response repeat the whole thing, and keep repeating until the array is empty.

How to run function after last function is finished in loop?

Below is my code
var request = require("request");
$('.xxx').siblings().each(function(i, elem) {
if (i === $('.xxx').siblings().length - 1) {
goToOrderDetail(true, i);
}
});
function goToOrderDetail(status, i) {
console.log('Processing' + i + 'data!');
var options = {
method: "POST",
url: "https://example.com"
}
request(options, function(error, response, body) {
console.log(response);
}
}
When I run this file on node.js, I will get message like below in my terminal.
Processing 1 data!
Processing 2 data!
Processing 3 data!
Processing 4 data!
Processing 5 data!
response message
response message
response message
response message
response message
But what I expect and want is
Processing 1 data!
response message
Processing 2 data!
response message
Processing 3 data!
response message
Processing 4 data!
response message
Processing 5 data!
response message
I know this is about sync or async issue, but How can I fix it?
How can I wait the goToOrderDetail function finished and then keep loop next element?
I did looked for async(enter link description here) package but have no idea which function I can use.
Your code is running well, but your console.log do not represent what is happening.
If you move your console.log like this
var options = {
method: "POST",
url: "https://example.com"
}
request(options, function(error, response, body) {
console.log('Processing' + i + 'data!');
console.log("test");
}
you will get
Processing 1 data!
test
Processing 2 data!
test
Processing 3 data!
test
Processing 4 data!
test
Processing 5 data!
test
It's not very clear what you want to do, or even how your function can get called that many times with the if(i === ...)that you put there. One way to really ensure that your requests really are called in a synchronous way is to "chain" them. It has the added benefit to state more clearly what you intend...
The following (not tested) code illustrates what I mean. Keep in mind that you lose the benefit of running parallel requests.
var request = require("request");
var numberOfRequests = $(".xxx").length;
function goToOrderDetail(status, index, maximum) {
console.log('Preparing' + index + 'th request!');
var options = {
method: "POST",
url: "https://example.com"
}
request(options, function(error, response, body) {
console.log("received " + index +"th request response : ");
console.log(response);
//here, the request is done. maybe we want to launch another one
if(index < maximum )
goToOrderDetail(status, index +1, maximum);
}
}
//call the function once, for the first request, and let the chaining happen
goToOrderDetail(true, 1, numberOfRequests);

node.js - making result available globally (Request module)

I'm trying to process the returned JSON result from the request
so I need to expand its scope outside this request call.
To do that I declared data variable with an empty string and assign the result to this data but it doesn't print the result.
How can I accomplish this?
module.exports = function(callback) {
var request = require("request")
var url = "http://sheetsu.com/apis/94dc0db4"
var data = "";
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
callback(body)
data = body;
}
})
console.log(data);
}
This is classic async confusion : your console.log call will happen before the http request callback.
Your script is executed in this order:
request() is executed
console.log(data)
request() callback function, where you asign data a value
If you want to print data, you must do it inside the request callback function. The async module, is very useful when performing async tasks, specially if you need to perform tasks in a specific order and use the data from this requests.

NodeJS... Saving JSON to a Variable

I'm a bit of a newbie to NodeJS, but I've looked around all over and can't seem to find a solution to my problem below. I'm sure it's something simple, but thanks in advance for all help you can give me!
I'm trying to make a simple JSON scraper via NodeJS. All I need is for JSON to be stored to a variable. The problem is, I'm using Require, and their example just logs it to console. I've tried adding a variable after it's logging to the console, but I'm just getting undefined. Here's my code below, it's pretty simplistic so far :)
// var jsonVariable; Doesn't work, shown as a test
function getJSON(url){
var request = require("request")
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body) // Print the json response
//return body; This doesn't work, nor does making a global variable called json and assigning it here. Any ideas?
//jsonVariable = body; // This also doesn't work, returning undefined even after I've called the function with valid JSON
}
})
}
Once again, thanks so much for any help you can give me :)
The problem is that the request method is asynchronous, but you're trying to synchronously return a result. You'll need to either make a synchronous request (which doesn't appear to be possible with the request package you're using), or else pass a callback function to be called when the request responds successfully. e.g.:
var request = require("request")
function getJSON(url, callback) {
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
callback(body);
}
});
}
getJSON('http://example.com/foo.json', function (body) {
console.log('we have the body!', body);
});
If you use 'return body' where does it return to? That function is being called as a parameter to the request() function. You also cannot define a variable in your anonymous function because you will not have access to it outside of that scope.
What you need to do is define a variable outside of function getJSON() and then save body to that.
e.g.,
var result;
function getJSON(url){
var request = require("request")
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
result = body;
}
});
}

how return data since a GET request with node.js

I have a little trouble with an Node application, the problem is: I have an Script in a web site "x" and this script calls a function that is on another server (like analytics), I'm calling the function with ajax and when the function returns the data, happen some curious, when I check the network with Developer Tools in Chrome, the callback shows the response like I wanted in JSON format, but not show me data. My code:
var xml2js = require('xml2js'),
http = require('http'),
request = require('request');
var parserController = function (aw){
console.log('Parse Controller load');
aw.get('/ads/:keyword/:sid/:pid/:count', function (req,res){
res.setHeader('Content-Type', 'application/json');
request('http://'+req.params.sid+'.'+req.params.pid+'.autoweb-xml.com/feed?&sid='+req.params.sid+'&auth=2Al5&subid=&q='+req.params.keyword+'&ip=127.0.0.1&ua=Mozilla/5.0%20(Windows%20NT%206.1;%20WOW64;%20rv:26.0)%20Gecko/20100101%20Firefox/26.0&ref=awebads.lan&count='+req.params.count+'&state=&city=', function (error, response, body) {
if (!error && response.statusCode == 200) {
var parser = xml2js.parseString;
var data = '';
parser(body,{explicitRoot : false}, function (err, result){
if(!err){
data = result;
dataP=data.results[0];
dataS=dataP.sponsored[0];
console.log(dataS.listing);
return res.send(dataS.listing);
}
else
{
console.log(err);
}
})
}
})//en del request
});
};
and my call function is:
var xhr = $.ajax({
type:'GET',
url:'http://HOST/ads/'+configParams.keyword+'/'+configParams.envSource+'/'+configParams.envPublisher+'/'+configParams.envCount,
dataType : 'jsonp',
async: false,
crossDomain : true
})
xhr.done(function (data){
console.log(data);
data.forEach(function(item){
window.collections.ads.add(item);
});
}).fail(function (err) {
//console.log('failed');
//console.log(err)
});
when I display the data in the console, this part show me the XMLHTTPRequest, thanks in advance for your help
You are sending JSON:
the callback shows the response like I wanted in JSON format
… but the client is expecting JSON-P
dataType : 'jsonp',
Either:
Tell the client to expect JSON (or just remove the dataType line and let it use the Content-Type header) and set Access-Control-Origin on the response headers to give the site permission to access it cross-domain or
Send JSON-P back instead (look at callback in the query string, send Content-Type: application/javascript (not JSON!), and return callback_value(your_json); as the response body.
In case of jsonp you need a callback function and then return your response in that callback.

Categories

Resources