How can I automate chaining a series of ajax requests? - javascript

Look at the lower part of my function: I want to repeat info(url_part1 + next + url_part2, function(next) { couple of times. Is there a smarter way than one presented below (maybe some kind of loop)? I've been thinking whole day and I can't devise anything.
function info(link, callback) {
$.getJSON(link, function(json) {
$.each(json.data.children, function(i, things) {
$("#threadlist").append('<img src="' + things.data.url + '">');
});
callback(json.data.after);
});
}
var url_first = "http://www.reddit.com/r/aww/.json?jsonp=?";
var url_part1 = "http://www.reddit.com/r/aww/.json?after=";
var url_part2 = "&jsonp=?";
info(url_first, function(next) {
info(url_part1 + next + url_part2, function(next) {
info(url_part1 + next + url_part2, function(next) {
info(url_part1 + next + url_part2, function(next) {
info(url_part1 + next + url_part2, function(next) {
});
});
});
});
});
Js fiddle: http://jsfiddle.net/rdUBD/1/

Maybe something like that:
http://jsfiddle.net/JwAbK/

You might want to consider processing them recursively.
function processRequest( request)
{
$.getJSON(request,function(json) {
// process json
if (json.data.after) {
processRequest( "http://www.reddit.com/r/aww/.json?after="
+ json.data.after
+ "&jsonp=?" );
}
});
}
processRequest("http://www.reddit.com/r/aww/.json?jsonp=?");

If I understand correctly it seems that all you want to do is call a function recursively, up to a certain number of times. Here is sample code that does exactly that:
function testFunction(number, callback) {
document.writeln("testFunction() called with number = " + number + "<br />");
callback(number + 1);
}
var CallCount = 0;
testFunction(1, function(next) {
CallCount++;
document.writeln("callback called next = " + next + "<br />");
if(CallCount == 5) {
document.writeln("callback called 5 times, don't call it again");
} else {
testFunction(next, arguments.callee);
}
});
That code outputs the following:
testFunction() called with number = 1
callback called next = 2
testFunction() called with number = 2
callback called next = 3
testFunction() called with number = 3
callback called next = 4
testFunction() called with number = 4
callback called next = 5
testFunction() called with number = 5
callback called next = 6
callback called 5 times, don't call it again
You can try it out at jFiddle: http://jsfiddle.net/luisperezphd/NQya6/
Applying this to your code you get:
var DebugCount = 0;
function EmulateGetJson(link, callback) {
DebugCount++;
callback({
data: {
children: [
{ data : { url: "https://www.google.com/images/srpr/logo3w.png?" + DebugCount, next: "next" } }
]
}
});
}
function info(link, callback) {
//$.getJSON(link, function(json) {
EmulateGetJson(link, function(json) {
$.each(json.data.children, function(i, things) {
$("#threadlist").append('<img src="' + things.data.url + '">');
});
callback(json.data.after);
});
}
var url_first = "http://www.reddit.com/r/aww/.json?jsonp=?";
var url_part1 = "http://www.reddit.com/r/aww/.json?after=";
var url_part2 = "&jsonp=?";
var CallCount = 0;
var TargetCallCount = 5;
info(url_first, function(next) {
CallCount++;
if(CallCount != TargetCallCount) {
info(url_part1 + next + url_part2, arguments.callee);
}
});
The jsFiddle for this can be found at: http://jsfiddle.net/luisperezphd/uY8Kj/
I emulated the call to $.getJSON in JavaScript code in order to provide a complete example. I appended a number to the end of the sample image URL to illustrate that a different URL was being returned each time.
arguments.callee refers to the current function, in this case the function you are passing as the callback to info() this is the key to the recursion.

Related

phantomjs: my page.evaluate(function()) is not taking the paramters i pass it as values and giving me null error

My code is as follows:
var page = new WebPage(), testindex = 0, loadInProgress = false;
var fs = require('fs');
var sheet = fs.read('courtcalllist.csv').split("\n").map(function(row){
return row.split(",");});
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onLoadStarted = function() {
loadInProgress = true;
console.log("load started");
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log("load finished");
};
for (var i = 1; i < sheet.length - 1; i ++ ){
year = sheet[i][8];
district = sheet[i][9];
casenumber = sheet[i][10];
var steps = [
function () {//first function to open page
page.open("http://www.cookcountyclerkofcourt.org/CourtCaseSearch/CourtCallSearch.aspx");
}, //first function bracket
function () {// second function calls page to evaulate page input
page.evaluate(function(year, district, casenumber) {
console.log("this is my test " + year, district, casenumber);
document.getElementById('ctl00_MainContent_txtCaseYear').value = year; //'2018';
document.getElementById('ctl00_MainContent_txtCaseCode').value = district;//'M3';
document.getElementById('ctl00_MainContent_txtCaseNumber').value = casenumber;//'005338';
return;
},year, district, casenumber);
}, //2nd function bracket
function () { // 3rd function calls evaluate click
//click
page.evaluate(function() {
document.getElementById('ctl00_MainContent_btnSearch').click();
});
}, //3rd function bracket
function () { // 4th function calls the 2nd page after data
// Output content of page to stdout after form has been submitted
page.evaluate(function() {
for (i = 1; i < 11; i++ ){
console.log(document.querySelectorAll('td')[i].innerHTML);
}
});
} //4thbracket
];
interval = setInterval(function() {
if (!loadInProgress && typeof steps[testindex] == "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
phantom.exit();
}
}, 50);
}
For some reason, the console.log WILL print the variables i pass as such:
this is my test 2018 M3 005338
Which is correct, that's what i need it to be, but when they're evaluated i get:
TypeError: null is not an object (evaluating 'document.getElementById('ctl00_MainContent_txtCaseYear').value = year')
undefined:3
The code above works if i hard code my values in it Which is what is commented out, but it won't take the variables i'm giving it.
Is my variable being turned from a string to an object therefore it can't be read? I'm at a loss here, i have even tried
document.getElementById('ctl00_MainContent_txtCaseYear').value = year.toString;
document.getElementById('ctl00_MainContent_txtCaseCode').value = district.toString;
document.getElementById('ctl00_MainContent_txtCaseNumber').value = caenumber.toString;
And it just gives me back the same error.
function () {
page.evaluate(function(string1, string2, string3) {
console.log("this is my test " + String(string1) + String(string2) + String(string3));//, district, casenumber);
document.getElementById('ctl00_MainContent_txtCaseYear').value = String(string1);//'2002';
// console.log("this is my test " + String(string2));
document.getElementById('ctl00_MainContent_txtCaseCode').value = String(string2);//'M1';//
// console.log("this is my test " + String(string3));
document.getElementById('ctl00_MainContent_txtCaseNumber').value = String(string3);//'144115'; //
return;
},year, district, casenumber);
Is how you pass variables. Notice the arguments go at the end, and they must be written as something else within the function()

Combining $.each functions

I'm using the $.each function in jQuery to assign and change classes and IDs on various elements on click. I was wondering if there is a way to combine these into a single function rather than having three separate functions.
var stored = $.each;
var myFunction = function() {
$(this).removeAttr("id");
};
function numbers() {
//function 1
stored($(".numbers"), function(index, value) {
var num = index + 1 + ".";
$(value).empty();
$(value).append(num);
});
//function 2
stored($(".weight-change"), function(index) {
myFunction();
$(this).attr("id", "weight" + index);
});
//function 3
stored($(".onebox"), function(index) {
myFunction();
$(this).attr("id", "shipprice1box" + index);
});
}
You can make a generic function and call it. There is no need to remove the attribute before you update it. Just a waste of processing time. attr supports a function so no need for each.
function updateIds (selector, prefix) {
$(selector).attr("id", function (index) { return prefix + index; });
}
updateIds(".weight-change", "weight");
updateIds(".onebox", "shipprice1box");
Here's how you can avoid code duplication (you can edit it further according to your needs).
var arr = ['.numbers', '.weight-change', '.onebox'];
stored($(arr.join()), function(index, value) {
if ($(this).is(arr[0])) {
var num = index + 1 + ".";
$(value).empty();
$(value).append(num);
}
else if ($(this).is(arr[1]) || $(this).is(arr[2])) {
myFunction();
if ($(this).is(arr[1])) {
$(this).attr("id", "weight" + index);
}
else if ($(this).is(arr[2])) {
$(this).attr("id", "shipprice1box" + index);
}
}
});

javascript setInterval not repeating in jquery

function get_stock_data(symbol, index) {
var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22"+ symbol +"%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=";
$.getJSON(url, function(data) {
var price = $(".stock-price");
price[index].innerHTML = "";
price[index].appendChild(document.createTextNode(data.query.results.quote.Change));
console.log(data);
}).success(function() {
console.log("success");
}).fail(function() {
console.log("Failed");
});
}
$("document").ready(function() {
var symbol = $(".stock-symbol");
for(var i = 0; i < symbol.length; i++) {
setInterval(get_stock_data(symbol[i].firstChild.textContent, i) , 1000);
console.log("hello");
}
});
The problem in this script is that get_stock_data function executes only once...plz help...i want the data to be updated to DOM..
Something like this should work.
function get_stock_data(symbol, index) {
var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22" + symbol + "%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=";
$.getJSON(url, function (data) {
var price = $(".stock-price");
price[index].innerHTML = "";
price[index].appendChild(document.createTextNode(data.query.results.quote.Change));
console.log(data);
}).success(function () {
console.log("success");
}).fail(function () {
console.log("Failed");
});
}
function setUpInterval() {
var symbol = $(".stock-symbol");
for (var i = 0; i < symbol.length; i++) {
setInterval("get_stock_data(" + symbol[i] + "," + i + ")", 1000);
}
}
setUpInterval();
You are calling get_stock_data in your setInterval call. So it gets called once and only once. You are actually passing undefined to setInterval, because get_stock_data doesn't return anything.
The first argument of setInterval should be the function you want to call. In this case, it looks like you want to call get_stock_data with some passed-in parameters. To make this work with setInterval, you'll need to pass in an anonymous function like this:
for (var i = 0; i < symbol.length; i++) {
setInterval(function() { get_stock_data(symbol[i].firstChild.textContent, i); }, 1000);
}
This way you are passing in the function to setInterval, which setInterval will call every 1000 (or so) milliseconds.

JSON return value to global variable

Simply my code looks like this:
var thevariable = 0;
For(){
//somecode using thevariable
$.getJSON('',{},function(e){
//success and i want to set the returned value from php to my variable to use it in the forloop
thevariable = e.result;
});
}
my main problem that the variable value stays "0", during the whole For loop, while i only want it to be "0" at the first loop, then it takes the result returned from PHP to use it on for loop.
here it my real code if you need to take a look:
var orderinvoice = 0;
for(var i=0; i<table.rows.length; i++){
var ordername = table.rows[i].cells[5].innerText;
var orderqty = ((table.rows[i].cells[1].innerText).replace(/\,/g,'')).replace(/Qty /g,'');
var orderprice = (table.rows[i].cells[2].innerText).replace(/\$/g,'');
var ordertype = table.rows[i].cells[3].innerText;
var orderlink = table.rows[i].cells[4].innerText;
$.getJSON('orderprocess.php', {'invoice': orderinvoice, 'pay_email': email, 'ord_name': ordername, 'ord_qty': orderqty, 'ord_price': orderprice, 'ord_type': ordertype, 'ord_link': orderlink}, function(e) {
console.log();
document.getElementById("result").innerText= document.getElementById("result").innerText + "Order #"+e.result+" Created Successfully ";
document.getElementById("invoker").innerText = ""+e.invoice;
orderinvoice = e.invoice;
if(i+1 == table.rows.length){
document.getElementById("result").innerText= document.getElementById("result").innerText + "With invoice #" + e.invoice;
}
});
in a loop block, before one ajax complete other one will be run and this's javascript natural treatment. For your case you can call a function at the end of success event. Do something like this:
var i = 0;
doSt();
function doSt() {
var orderinvoice = 0;
var ordername = table.rows[i].cells[5].innerText;
var orderqty = ((table.rows[i].cells[1].innerText).replace(/\,/g, '')).replace(/Qty /g, '');
var orderprice = (table.rows[i].cells[2].innerText).replace(/\$/g, '');
var ordertype = table.rows[i].cells[3].innerText;
var orderlink = table.rows[i].cells[4].innerText;
$.getJSON('orderprocess.php', { 'invoice': orderinvoice, 'pay_email': email, 'ord_name': ordername, 'ord_qty': orderqty, 'ord_price': orderprice, 'ord_type': ordertype, 'ord_link': orderlink }, function(e) {
console.log();
document.getElementById("result").innerText = document.getElementById("result").innerText + "Order #" + e.result + " Created Successfully ";
document.getElementById("invoker").innerText = "" + e.invoice;
orderinvoice = e.invoice;
if (i + 1 == table.rows.length) {
document.getElementById("result").innerText = document.getElementById("result").innerText + "With invoice #" + e.invoice;
}
i++;
if (i < table.rows.length) doSt();
});
}
I think you need a recursive function that always deals with the first element in your rows array and then splices it off and calls itself. For example, something like this:
function getStuff(rows, results) {
if (rows.length > 0) {
var ordername = rows[0].cells[5].innerText;
$.getJSON('orderprocess.php', { 'ord_name': ordername }, function (e) {
// do some stuff
results.push('aggregate some things here?');
rows.splice(0, 1);
return getStuff(rows, results);
});
} else {
return results;
}
}
When the array is spent, results will be returned with whatever aggregate you wanted at the end of the cycle. Then, you can do as you please with the results. I think you can also manipulate the DOM inside the function as you see fit if that makes more sense. Hope this helps.

Async iterator gives TypeError: undefined is not a function

I am trying to learn how to use the async module in node.js and I fall into to the following problem:
I first wrote this script which works fine (to my understanding)
var async = require('async');
var seconds_values = [];
process();
function process() {
var names = ['One', 'Two', 'ten', 'hello'];
modifications(names);
}
function modifications(somenames) {
async.each(somenames, function (one_name, callback) {
var random_num = Math.floor((Math.random() * 100000000) + 1);
seconds_values.push(one_name + '_' + random_num);
callback();
}, function(err){
async.each(seconds_values, function (one_value, callback) {
console.log(one_value);
callback();
},
function(err){
console.log('==== The END ===');
});
});
}
The I tried to assign the iterator to a variable, to make the code more readable.
var async = require('async');
var seconds_values = [];
process();
function process() {
var names = ['One', 'Two', 'ten', 'hello'];
modifications(names);
}
var first_function = function (one_name, callback) {
var random_num = Math.floor((Math.random() * 100000000) + 1);
seconds_values.push(one_name + '_' + random_num);
callback();
}
function modifications(somenames) {
async.each(somenames, first_function, function(err){
async.each(seconds_values, function (one_value, callback) {
console.log(one_value);
callback();
},
function(err){
console.log('==== The END ===');
});
});
}
The second script gives me the following error:
iterator(x, only_once(done) );
^
TypeError: undefined is not a function
I think I am missing something fundamental here. Could you please point me out what, if possible?
The error occurs because when the process runs, it calls modifications, but at this time, first_function is not defined yet.
You can have two options:
1.put the declaration before process call:
var first_function = function (one_name, callback) {
var random_num = Math.floor((Math.random() * 100000000) + 1);
seconds_values.push(one_name + '_' + random_num);
callback();
}
process();
2. use function declaration:
function first_function(one_name, callback) {
var random_num = Math.floor((Math.random() * 100000000) + 1);
seconds_values.push(one_name + '_' + random_num);
callback();
}
Also see here: Link

Categories

Resources