First off, sorry for it not being so neat, I am still learning the ropes of javascript.
I am running this code in the google chrome console, but it takes too much time to run it, is there anything I am doing, that I can fix to make it run faster?
function snipebot(page, max_page, max_price){
$.getJSON('http://www.roblox.com/catalog/json?browse.aspx?Subcategory=2&Keyword=&CurrencyType=0&pxMin=0&pxMax=0&SortType=2&SortAggregation=0&SortCurrency=0&LegendExpanded=true&Category=2&PageNumber=' + page, function(data){
$.each(data, function(index, item){
if (item['BestPrice'] <= max_price){
$.get('http://www.roblox.com/Item.aspx?id=' + item['AssetId'], function(data){
var purchaseData = $($(data).find(".PurchaseButton")[0]).data();
if (purchaseData['expectedPrice'] <= item['BestPrice']){
$.post('/API/Item.ashx?rqtype=purchase&productID=' + purchaseData['productId'] + '&expectedCurrency=1&expectedPrice=' + purchaseData['expectedPrice'] + '&expectedSellerId=' + purchaseData['expectedSellerId'] + '&userAssetID=' + purchaseData['userassetId'], function(){
console.log('[' + item['BestPrice'] + ']' + item['Name'] + item['AssetId'] + ' user:' + purchaseData['seller-name'] + ' ' + '#' + new Date().toTimeString())
});
} else {
console.log("Detected purchase:" + item['Name'] + item['AssetId'] + ' ' + purchaseData['seller-name']);
}
});
};
});
setTimeout(function(){
snipebot(page + 1 > max_page ? 1 : page + 1, max_page, max_price);
});
});
};
snipebot(1, 4, 50);
In the worst case, a call to snipebot() makes 3 round trip to the backend. You should review your design and move some of your logic to the backend to reduce the round-trips.
if (item['BestPrice'] <= max_price){ ...
if (purchaseData['expectedPrice'] <= item['BestPrice']){ ...
Both conditions above can be tested at the backend and processed there.
Related
I am developing a javascript app.
I have stuck to implementing this.
I am able to load all characters but I want to implement :- load one characters after on completion load next characters.
One characters at a time.
I want to load one character. After completion load next then again after completion next but one character at a time.
https://hanziwriter.org/docs.html
var chars = new Array('我','很','爱');
console.log(chars);
for(i=0; i< chars.length; i++){
console.log(chars[i]);
writeFunction(chars[i])
}
//c = '我';
function writeFunction(c){
var writer = HanziWriter.create('character-target-div' , c , {
width: 150,
height: 150,
showCharacter: false,
padding: 5
});
writer.quiz({
onMistake: function(strokeData) {
console.log('Oh no! you made a mistake on stroke ' + strokeData.strokeNum);
console.log("You've made " + strokeData.mistakesOnStroke + " mistakes on this stroke so far");
console.log("You've made " + strokeData.totalMistakes + " total mistakes on this quiz");
console.log("There are " + strokeData.strokesRemaining + " strokes remaining in this character");
},
onCorrectStroke: function(strokeData) {
console.log('Yes!!! You got stroke ' + strokeData.strokeNum + ' correct!');
console.log('You made ' + strokeData.mistakesOnStroke + ' mistakes on this stroke');
console.log("You've made " + strokeData.totalMistakes + ' total mistakes on this quiz');
console.log('There are ' + strokeData.strokesRemaining + ' strokes remaining in this character');
},
onComplete: function(summaryData) {
console.log('You did it! You finished drawing ' + summaryData.character);
console.log('You made ' + summaryData.totalMistakes + ' total mistakes on this quiz');
flagComplete = true;
}
});
}
<script src="https://cdn.jsdelivr.net/npm/hanzi-writer#2.2/dist/hanzi-writer.min.js"></script>
<div id="character-target-div"></div>
So you want to only continue your loop when the user has completed the character. That means your loop must become asynchronous.
JavaScript offers async and await for that purpose. The only requirement is that you provide a promise that resolves when the character is completed.
Here is how it could work (untested):
(async function() { // <-- add this wrapper
var chars = new Array('我','很','爱');
console.log(chars);
for(i=0; i< chars.length; i++){
console.log(chars[i]);
await writeFunction(chars[i]);
// ^^^^^
}
})(); // execute immediately
//c = '我';
// Make the function async, so it returns a promise
async function writeFunction(c) {
// Wrap the code inside a Promise constructor callback:
return new Promise(function (resolve, reject) {
var writer = HanziWriter.create('character-target-div' , c , {
width: 150,
height: 150,
showCharacter: false,
padding: 5
});
writer.quiz({
onMistake: function(strokeData) {
console.log('Oh no! you made a mistake on stroke ' + strokeData.strokeNum);
console.log("You've made " + strokeData.mistakesOnStroke + " mistakes on this stroke so far");
console.log("You've made " + strokeData.totalMistakes + " total mistakes on this quiz");
console.log("There are " + strokeData.strokesRemaining + " strokes remaining in this character");
},
onCorrectStroke: function(strokeData) {
console.log('Yes!!! You got stroke ' + strokeData.strokeNum + ' correct!');
console.log('You made ' + strokeData.mistakesOnStroke + ' mistakes on this stroke');
console.log("You've made " + strokeData.totalMistakes + ' total mistakes on this quiz');
console.log('There are ' + strokeData.strokesRemaining + ' strokes remaining in this character');
},
onComplete: function(summaryData) {
console.log('You did it! You finished drawing ' + summaryData.character);
console.log('You made ' + summaryData.totalMistakes + ' total mistakes on this quiz');
// call resolve: that does the magic!
resolve();
}
});
});
}
Like this?
I cannot test it since I have no idea how to correctly stroke any of these
You can change
setTimeout(writeFunction, 1000)
to
writeFunction();
if you do not want a pause
var chars = new Array('我', '很', '爱'),
cnt = 0;
writeFunction()
//c = '我';
function writeFunction() {
if (cnt >= chars.length) return
c = chars[cnt]
var writer = HanziWriter.create('character-target-div', c, {
width: 150,
height: 150,
showCharacter: false,
padding: 5
});
writer.quiz({
onMistake: function(strokeData) {
console.log('Oh no! you made a mistake on stroke ' + strokeData.strokeNum);
console.log("You've made " + strokeData.mistakesOnStroke + " mistakes on this stroke so far");
console.log("You've made " + strokeData.totalMistakes + " total mistakes on this quiz");
console.log("There are " + strokeData.strokesRemaining + " strokes remaining in this character");
},
onCorrectStroke: function(strokeData) {
console.log('Yes!!! You got stroke ' + strokeData.strokeNum + ' correct!');
console.log('You made ' + strokeData.mistakesOnStroke + ' mistakes on this stroke');
console.log("You've made " + strokeData.totalMistakes + ' total mistakes on this quiz');
console.log('There are ' + strokeData.strokesRemaining + ' strokes remaining in this character');
},
onComplete: function(summaryData) {
console.log('You did it! You finished drawing ' + summaryData.character);
console.log('You made ' + summaryData.totalMistakes + ' total mistakes on this quiz');
flagComplete = true;
cnt++
setTimeout(writeFunction, 1000)
}
});
}
<script src="https://cdn.jsdelivr.net/npm/hanzi-writer#2.2/dist/hanzi-writer.min.js"></script>
<div id="character-target-div"></div>
I'm using AngularJS to prefetch images in cache client and then I want to animate those prefetched images.
My code for the prefetching:
$scope.prefetch=function(limit) {
for (var i=0; i<limit; i++) {
var date = new Date($scope.dt);
if ($scope.fileFlag == false) {
if ($scope.viewmodel.timeResolution == 'yearly')
date = new Date(date.setFullYear(date.getFullYear() + i));
else if ($scope.viewmodel.timeResolution == 'monthly')
date = new Date(date.setMonth(date.getMonth() + i));
else if ($scope.viewmodel.timeResolution == 'daily') {
date = new Date(date.setDate(date.getDate() + i));
}
} else {
date = $scope.files[$scope.files.indexOf($scope.idSelectedVote) + i];
}
console.log( $http.get(site_url + "mwf/" + $scope.viewmodel.dataSet + "/" + $scope.viewmodel.varName + "/" + $scope.viewmodel.region + "/" + date + "/map/?vMin=" + $scope.VMin + "&vMax=" + $scope.VMax + "&type=" + $scope.viewmodel.type + "&cmap=" + $scope.viewmodel.colorMap, {'cache': true}));
}
};
then i do something like this to play those images
$scope.play=function(limit) {
for (var i=0; i<limit; i++) {
$scope.map.src= site_url + "mwf/" + $scope.viewmodel.dataSet + "/" + $scope.viewmodel.varName + "/" + $scope.viewmodel.region + "/" + parseInt(date)+i + "/map/?vMin=" + $scope.VMin + "&vMax=" + $scope.VMax + "&type=" + $scope.viewmodel.type + "&cmap=" + $scope.viewmodel.colorMap;
$scope.sleepFor(500);
}
};
$scope.sleepFor = function( sleepDuration ) {
var now = new Date().getTime();
while(new Date().getTime() < now + sleepDuration){ /* do nothing */ }
}
My problem is when I call play(4) it displays only the first and the last images and not an animation. Any idea on how can I improve this code or a different approach so I can do this?
Your sleepFor is an idle loop: you spin and do nothing, but you prevent any other work from being done. This is not the way in Javascript to delay work for a set period of time, or schedule a function to be run at a later time. In Javascript we use window.setTimeout -- and in Angular we have the convenient $timeout service to provide that:
$scope.play = function(limit) {
for (var i=0; i < limit; i++) {
$scope.map.src = site_url + "mwf/" + $scope.viewmodel.dataSet + "/" + $scope.viewmodel.varName + "/" + $scope.viewmodel.region + "/" + parseInt(date)+i + "/map/?vMin=" + $scope.VMin + "&vMax=" + $scope.VMax + "&type=" + $scope.viewmodel.type + "&cmap=" + $scope.viewmodel.colorMap;
var nextFrameMs = 500;
$timeout($scope.play, nextFrameMs);
}
};
In your example, wherever your $scope is provided to you -- assuming this is in a controller, you will have some line like module.controller($scope, ...) -- you will have to inject the $timeout service to be able to use it.
Additional resources:
Angular's documentation on $timeout
MDN documentation of window.setTimeout
You have to use intervals otherwise your code will block the execution of other code
Using Angular's built in $interval service is the solution:
var playInterval;
$scope.play = function(limit) {
var interval = 1000 / 20; //20 frames per second
var i = 0;
$interval.cancel(playInterval); //stop previous animations if any
if(i < limit) {
$scope.map.src = getSrc(i++);
var cache = $interval(function() {
if(i >= limit) {
return $interval.cancel(playInterval); //or you can replace with `i = 0;` to loop the animation
}
$scope.map.src = getSrc(i++);
}, interval);
}
};
function getSrc(i) {
return site_url + "mwf/" + $scope.viewmodel.dataSet + "/" + $scope.viewmodel.varName + "/" + $scope.viewmodel.region + "/" + parseInt(date)+i + "/map/?vMin=" + $scope.VMin + "&vMax=" + $scope.VMax + "&type=" + $scope.viewmodel.type + "&cmap=" + $scope.viewmodel.colorMap;
}
So I have this code that I am running inside of the google chrome console, and every time that I try to run it it give me unexpected identifier on line: 12. I went to that line and it is the setTimeout. I really don't know how to fix this, I tried to just call snipebot() but that didn't work either.
function snipebot(itemID, max_price){
var ItemURL = "http://www.roblox.com/Item.aspx?id=" + itemID;
$.get(ItemURL, function(data){
var purchaseData = $($(data).find(".PurchaseButton")[0]).data();
if (purchaseData['expectedPrice'] <= max_price){
$.post('/API/Item.ashx?rqtype=purchase&productID=' + purchaseData['productId'] + '&expectedCurrency=1&expectedPrice=' + purchaseData['expectedPrice'] + '&expectedSellerId=' + purchaseData['expectedSellerId'] + '&userAssetID=' + purchaseData['userassetId'], function(){
console.log('[' + purchaseData['expectedPrice'] + ']');
});
}
}
setTimeout(function(){
snipebot(itemID, max_price);
});
};
snipebot(18426536, 140);
It's unexpected because your call to $.get hasn't been closed properly on the previous line:
function snipebot(itemID, max_price){
var ItemURL = "http://www.roblox.com/Item.aspx?id=" + itemID;
$.get(ItemURL, function(data){
var purchaseData = $($(data).find(".PurchaseButton")[0]).data();
if (purchaseData['expectedPrice'] <= max_price){
$.post('/API/Item.ashx?rqtype=purchase&productID=' + purchaseData['productId'] + '&expectedCurrency=1&expectedPrice=' + purchaseData['expectedPrice'] + '&expectedSellerId=' + purchaseData['expectedSellerId'] + '&userAssetID=' + purchaseData['userassetId'], function(){
console.log('[' + purchaseData['expectedPrice'] + ']');
});
}
}); // <-- here
setTimeout(function(){
snipebot(itemID, max_price);
}, 2000); // <!-- See below
};
snipebot(18426536, 140);
Also note my second comment, where you've missed the 2nd parameter to setTimeout, namely how long to delay for. I've added in a two second delay as an example. Without this, it defaults to 0, which may or may not be what you intended.
In the following snippet of my code, I post to a link, from which it allows me to change the title, but will not call the function info() with the argument supplied, nor will it log in the console, please help with this code, thanks. Also, please note all the variables are defined and this code works 100% besides this, and it won't work with $.get rather than $.post either.
function info(text, state) {
$("<h4>"+text+"</h4>").appendTo("body");
if (state != "run") {
$("h2").text(text).fadeIn("slow").delay(30000).fadeOut();
}
$.post(buy, function(r) {
diff = event.timeStamp - last;
$(document).prop('title', 'Purchased '+info['itemName']+'!');
info('Purchased '+info['itemName']+' for '+info['expectedPrice']+' in '+diff+' milliseconds!');
console.log('Purchased '+info['itemName']+' for '+info['expectedPrice']+' in '+diff+' milliseconds!');
})
--EDIT--
If I put console.log above info, the code works excluding the info() function, so the problem is possibly there
Try (this pattern)
// var last = $.now();
function info(text, state) {
$("<h4>" + text + "</h4>").appendTo("body");
if (state != "run") {
$("h2").text(text).fadeIn("slow").delay(30000).fadeOut();
}
// missing closing `{` at OP
};
$.post(buy, function (_info) {
// `_info` : return json object
// `info` : function declaration name
// diff = $.now() - last;
$(document).prop('title', 'Purchased ' + _info['itemName'] + '!');
info('Purchased '
+ _info['itemName'] + ' for '
+ _info['expectedPrice'] + ' in '
+ diff + ' milliseconds!'
, "run");
console.log('Purchased '
+ _info['itemName'] + ' for '
+ _info['expectedPrice'] + ' in '
+ diff + ' milliseconds!');
});
jsfiddle http://jsfiddle.net/guest271314/7vxb7336/
Hey there,
Again, I've been searching a solution to find out why a function, would not being called... and guess what, I did not find.
I have a form, that I submit using jQuery Ajax. When error, I get every local data, I got, I sorted them, and show them to the user.
Here is the sample code :
$.ajax({
type: "POST",
url: "http://xxx/register.php",
data: form,
success: function(msg){
//console.log("Data Saved: " + msg);
$.iGrowl(2,stringdata[4]);
var data = parseJSON(msg);
if(data.msg.score != undefined){
var cpt = 0;
$.each(data.msg.score, function(index,el){
if(cpt<8){
if(el.selected)
$('tbody').append('<tr class="win"><td>' + el.name + '</td><td>' + el.score + '</td></tr>');
else
$('tbody').append('<tr><td>' + el.name + '</td><td>' + el.score + '</td></tr>');
}
});
}
else{
$.iGrowl(3,"Erreur inconnue...");
}
$("#scorediv").css("visibility","visible");
$( "#formule" ).css('opacity',0);
$( "#scorediv" ).css('opacity',1);
},
error: function(data) {
cpt = 0;
var i = 0;
score.each(function(r){
arrayScore[i] = r;
i++;
});
arrayScore.sort(function(a, b){
console.log("sorting...");
if(a[3])
{
if(b[3])
{
return (b[3].value - a[3].value); //causes an array to be sorted numerically and descending
}
}
});
$.each(arrayScore, function(index,el){
//arrayScore.forEach(function(el) {
//score.each(function(el){
if(cpt<8)
{
if(el[2].value == form[2].value)
$('tbody').append('<tr class="win"><td>' + el[1].value + '</td><td>' + el[3].value + '</td></tr>');
else
$('tbody').append('<tr><td>' + el[1].value + '</td><td>' + el[3].value + '</td></tr>');
cpt++;
}
else
return false;
});
var user = form;
store.save(user, function(r) {
});
$.iGrowl(3,stringdata[5]);
$("#scorediv").css("visibility","visible");
$("#formule").css('opacity',0);
$( "#scorediv" ).css('opacity',1);
}
});
My array is never sorted. If I change this part :
var i = 0;
score.each(function(r){
arrayScore[i] = r;
i++;
});
by this :
score.each(function(r){
arrayScore.push(r);
});
arrayScore is never filled.
I try to execute each line in the console step by step, it works.... I'm getting kind of crazy... and I really do not know what could have happened ?
Any help would be graceful appreciate !
P.S : I'm using, jQuery1.5 + Lawnchair and CSS3 animation.
Code tested on safari and chrome.
Thanks !
Javascript array objects don't support a method called each. You should try
$.each(score, function(index, value){...});