Updating varibles and running functions using setTimeout - javascript

I'm trying to send a drone a new set of coordinates every 1/2 of a second. Right now, it's not working the way I planned on it working (aka it's not working at all). I have 90 different Lat, Long, and Alt coordinates all predetermined inside my .js file. They are listed like this-
setTimeout(function () {long_in=-74.61122515230907;lat_in=41.05861743700108;alt_in=10}, 5000);
setTimeout(function () {long_in=-74.61124258212661;lat_in=41.05864962647036;alt_in=10}, 10000);
setTimeout(function () {long_in=-74.61125021662482;lat_in=41.05867214783328;alt_in=10}, 15000);
and so on...
Then they will need to pass thru this function -
if (coordinate == "GPS") {
console.log("GPS go");
lat_out = lat_in;
long_out = long_in;
alt_out = alt_in;
console.log(lat_out, long_out, alt_out)
}
And finally it will send this command to the drone-
var msgdata = {};
msgdata["twist"] = {};
msgdata.twist["twist"] = {};
msgdata.twist.twist["linear"] = {};
msgdata.twist.twist.linear["x"] = lat_out;
msgdata.twist.twist.linear["y"] = long_out;
msgdata.twist.twist.linear["z"] = alt_out;
msgdata.twist.twist["angular"] = {};
msgdata.twist.twist.angular["z"] = 1.00;
msgdata["tolerance"] = 2.00;
msgdata["async"] = true;
msgdata["relative"] = false;
msgdata["yaw_valid"] = true;
msgdata["body_frame"] = false;
$.ajax({
type: "POST",
dataType: "json",
data: JSON.stringify(msgdata),
url: "http://" + ip + "/ros/" + namespace + "/navigation/position_set",
success: function (data) {
console.log(data, "Coordinates sent", lat_out,long_out,alt_out);
}
});
I have defined all of my variables prior to this code globally. All of the commands work perfectly fine, I just can't get them to all refresh every 1/2 of a second. Do I need to have all of these commands inside every setTimeout or something? Thanks for the help.

Yes you need to make the call again and again. You could wrap it in a function and make the call happen again and again from the setTimeout.
I have created a callback chain to guarantee order of execution based on #Liam's recommendation and the comments discussion.
setTimeout(function() {
long_in = -74.61122515230907;
lat_in = 41.05861743700108;
alt_in = 10;
prepSignal(long_in, lat_in, alt_in, function() {
setTimeout(function() {
long_in = -74.61124258212661;
lat_in = 41.05864962647036;
alt_in = 10;
prepSignal(long_in, lat_in, alt_in, function() {
setTimeout(function() {
long_in = -74.61125021662482;
lat_in = 41.05867214783328;
alt_in = 10;
prepSignal(long_in, lat_in, alt_in);
}, 5000);
});
}, 5000);
});
}, 5000);
var coordinate = "GPS";
function prepSignal(long_in, lat_in, alt_in, callback) {
if (coordinate == "GPS") {
console.log("GPS go");
lat_out = lat_in;
long_out = long_in;
alt_out = alt_in;
console.log(lat_out, long_out, alt_out, callback);
sendSignal(long_in, lat_in, alt_in, callback);
}
function sendSignal(long_in, lat_in, alt_in, cb) {
var msgdata = {};
msgdata["twist"] = {};
msgdata.twist["twist"] = {};
msgdata.twist.twist["linear"] = {};
msgdata.twist.twist.linear["x"] = lat_out;
msgdata.twist.twist.linear["y"] = long_out;
msgdata.twist.twist.linear["z"] = alt_out;
msgdata.twist.twist["angular"] = {};
msgdata.twist.twist.angular["z"] = 1.00;
msgdata["tolerance"] = 2.00;
msgdata["async"] = true;
msgdata["relative"] = false;
msgdata["yaw_valid"] = true;
msgdata["body_frame"] = false;
$.ajax({
type: "POST",
dataType: "json",
data: JSON.stringify(msgdata),
url: "http://" + ip + "/ros/" + namespace + "/navigation/position_set",
success: function(data) {
console.log(data, "Coordinates sent", lat_out, long_out, alt_out);
if(cb && typeof cb == "function") {
cb();
}
}
});
}
}

You have to run recalculation inside setTimeout after you set a value.

Related

Big foreach freeze DOM

There is a script that processes lines from a text file and sends it to the server. The server, meanwhile, returns a response and fills in the required information.
The problem is that when you try to download a file with about a million entries, the browser freezes and takes a very long time to process.
Is it possible to make this process without browser delays?
document.getElementById('file').onchange = function() {
$('#uploader-after').show();
$('#uploader-before').hide();
$("#file").prop('disabled', true);
var o_time = performance.now();
$('o_total').text("");
$('o_errors').text("");
$('o_time').text("");
var file = this.files[0];
var count = 1;
var errorCount = 0;
$('.file-name').text(file.name);
var reader = new FileReader(file);
reader.onload = function(progressEvent) {
var lines = this.result.split('\n');
$('#find-count').text(lines.length);
for(var line = 0; line < lines.length; line++) {
//setTimeout( function() { // i try this, but dont work
jQuery.ajax({
'async': true,
'global': false,
'type': "POST",
'url': 'getFile.php',
'data': { url: lines[line] },
'dataType': "json",
'success': function(data) {
var answer = data.answer ? data.answer : "";
var id = data.id ? data.id : "";
$('#proc-count').text(count);
var proc = Math.round(count / lines.length * 100);
$('proc').text(proc);
$("#pg-bar-line").css("width", proc + "%");
count++;
if(id == "") {
errorCount++;
}
$('o_total').text(count - 1);
$('o_errors').text(errorCount);
scannert.DataTable().row.add([id, data.inputURL, answer]).draw(false);
if(count === lines.length) {
o_time = performance.now() - o_time;
$('o_time').text(msToTime(o_time));
$('.otchet').show();
$('#uploader-after').hide();
$('#uploader-before').show();
$("#file").prop('disabled', false);
}
},
'error': function() {
count++;
}
});
//}, 5);
}
};
reader.readAsText(file);
};
Ill try setTimeout, but it doesnt work -_-

How to wait for forEach to complete when each iteration calls an asynchronous options?

Alright, here's what the plan is. Go through each file, add the file into the array. Once all files are added, then combine them using the JSZipUtility and Docxtemplater:
'click .merge-icon': (e) => {
var programId = Router.current().url.split('/').pop();
var programObj = Programs.findOne(programId);
var insertedDocuments = [];
var i = 0;
var count = programObj.activityIds.count;
var fileDownloadPromise = new Promise((resolve, reject) => {
programObj.activityIds.forEach(function(activityId) {
var activityObj = Activities.findOne(activityId);
var documentObj = ActivityFiles.findOne(activityObj.documents.pop()._id);
JSZipUtils.getBinaryContent(documentObj.url(), callback);
function callback(error, content) {
var zip = new JSZip(content);
var doc = new Docxtemplater().loadZip(zip);
var xml = zip.files[doc.fileTypeConfig.textPath].asText();
xml = xml.substring(xml.indexOf("<w:body>") + 8);
xml = xml.substring(0, xml.indexOf("</w:body>"));
xml = xml.substring(0, xml.indexOf("<w:sectPr"));
insertedDocuments.push(xml);
i++;
if (i == count - 1) {
resolve();
}
}
});
});
fileDownloadPromise.then(() => {
JSZipUtils.getBinaryContent('/assets/template.docx', callback);
function callback(error, content) {
console.log(content);
var zip = new JSZip(content);
var doc = new Docxtemplater().loadZip(zip);
setData(doc);
}
function setData(doc) {
doc.setData({
body: insertedDocuments.join('<w:br/><w:br/>')
});
doc.render();
useResult(doc);
}
function useResult(doc) {
var out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
});
saveAs(out, programObj.name + '.docx');
}
});
}
Turns out nothing's happening. What's wrong with the execution of this Promise here ?
I'm only calling resolve when every file has been loaded in the array.

Loop through XML files jQuery

I am a bit stuck with the following problem.
I have several XML files tagged by an ID (every XML is id'd by a value). I am now trying to loop through these files and output its contents to HTML.
However it starts the loop before it does the call back
Loop0
Loop1
Loop2
Callback0
Callback1
Callback2
I would need
Loop0
Callback0
Loop1
Callback1
As I need to control the results at some point.
var allContent=["xmlfile1","xmlfile2","xmlfile3","xmlfile4"];
var totalSearch = 0;
var countSearch = 0;
function doSearch() {
var oldContentID = contentID;
for (iSearch=0;iSearch<allContent.length;iSearch++) {
totalSearch = totalSearch + countSearch;
contentID = allContent[iSearch];
defineContent();
getXML();
}
}
function getXML() {
$.ajax({
type: "GET",
url: langFile,
dataType: "xml",
beforeSend: function(){
$('#results-list').empty();
$('#results-list').hide();
$('#loading').addClass('loading');
},
success: function(xml) {
var totalElements;
var intSearch = 0;
totalSearch = totalSearch + countSearch;
countSearch = 0;
var searchText = $('#text').val().toLowerCase();
totalElements = $(xml).find('news').length;
while (intSearch < totalElements) {
oFeed = $(xml).find('news:eq('+intSearch+')');
var headline = oFeed.find('headline').text();
var newsText = oFeed.find('detail').text();
var section = oFeed.find('section').text();
var category = oFeed.attr('category');
var stripEnters = newsText.match(/\r?\n|\r/gi);
if (stripEnters != null) {
for (var s = 0; s < stripEnters.length ; s++ ){
newsText = newsText.replace(stripEnters[s],'');
}
}
var newsText2 = $.htmlClean(newsText, {format:true});
var newsText3 = $(newsText2)
var newsText4 = $(newsText3).text();
var newsText5 = newsText4.replace( /\W/gi, "" );
if (section.toLowerCase() == "news" || section.toLowerCase() == "featured") {
if (headline.toLowerCase().indexOf(searchText) >= 0) {
$('<dt></dt>').html(headline).appendTo('#results-list');
$('<dd></dd>').html(newsText).appendTo('#results-list');
countSearch++;
}//end if
else if (newsText5.toLowerCase().indexOf(searchText) >= 0) {
$('<dt></dt>').html(headline).appendTo('#results-list');
$('<dd></dd>').html(newsText).appendTo('#results-list');
countSearch++;
}
}
intSearch++;
}
}
});
}
At the end of the call backs I need to run the following, however it now executes this function before it finishes all call backs.
function displayResults() {
if (totalSearch == 0)
{
alert("No results found");
$('#loading').removeClass('loading');
$('#main').fadeIn(1000);
}
else {
dynamicFaq();
$('<p></p>').html(totalSearch + ' Results found').prependTo('#results-list');
$('#results-list').fadeIn(1000);
$('#loading').removeClass('loading');
}
}
If I understood you correctly, you want to load 1 xml file, loop, and then start to load the next xml file. If so, here is a little pseudo code:
function doSearch(int xmlFileIterator){
if (xmlFileIterator < allContent.length) {
...
contentID = allContent[xmlFileIterator];
...
getXml(xmlFileIterator);
} else {
//no more xml files left
displayResults();
}
}
function getXml(int xmlFileIterator) {
...
success: function() {
...
doSearch(++xmlFileIterator);
}
}
The first call is doSearch(0) which loads the first xml file. After the file is loaded and the loop is done (in success) you can call the doSearch function again with a higher number (iterator).
I see your AJAX call is Asynchronous. Try using
....
type: "GET",
url: langFile,
async: false,
dataType: "xml",
.....
Maintain a ajax queue so thos ajax call will be done one by one. plus maintain a global variable searchedCount which will maintain how main xml are proccessed.
In complete callback of ajax check for the searchedCount and call displayResults function .
var allContent = ["xmlfile1", "xmlfile2", "xmlfile3", "xmlfile4"];
var totalSearch = 0;
var countSearch = 0;
var searchedCount = 0;
var ajaxQueue = $({});
$.ajaxQueue = function (ajaxOpts) {
// Hold the original complete function.
var oldComplete = ajaxOpts.complete;
// Queue our ajax request.
ajaxQueue.queue(function (next) {
// Create a complete callback to fire the next event in the queue.
ajaxOpts.complete = function () {
// Fire the original complete if it was there.
if (oldComplete) {
oldComplete.apply(this, arguments);
}
// Run the next query in the queue.
next();
};
// Run the query.
$.ajax(ajaxOpts);
});
};
function doSearch() {
var oldContentID = contentID;
searchedCount = 0;
for (iSearch = 0; iSearch < allContent.length; iSearch++) {
totalSearch = totalSearch + countSearch;
contentID = allContent[iSearch];
defineContent();
searchedCount++;
getXML();
}
}
function getXML() {
$.ajaxQueue({
type: "GET",
url: langFile,
dataType: "xml",
beforeSend: function () {
$('#results-list').empty();
$('#results-list').hide();
$('#loading').addClass('loading');
},
success: function (xml) {
//your code
},
complete: function () {
if (searchedCount == allContent.length) {
displayResults()
}
}
});
}

Javascript Function Returns Undefined JSON Object (But It's Not Undefined!)

I am trying to return a JSON object from a function using the JSON jQuery plugin (http://code.google.com/p/jquery-json/) but after returning the object from the function, it becomes undefined.
$(document).ready(function() {
var $calendar = $('#calendar');
$calendar.weekCalendar({
...
data : function(start, end, callback) {
var datas = getEventData();
alert(datas); // Undefined???
}
});
If I inspect the object before returning it, it is defined.
function getEventData() {
var dataString = "minDate="+ minDate/1000 + "&maxDate=" + maxDate/1000;
//alert(dataString);return false;
$.ajax({
type: "POST",
url: "busker_ops.php",
data: dataString,
dataType: "json",
success: function(data) {
if(data != null) {
var jsonArray = new Array();
var jsonObj = {};
for(var i = data.length - 1; i >= 0; --i) {
var o = data[i];
var set_id = o.set_id;
var start = o.startOrig;
var end = o.endOrig;
var title = o.title;
var deets = o.deets;
jsonObj =
{
"id":parseInt(set_id),
"start":$("#calendar").weekCalendar("formatDate", new Date(start), "c"),
"end":$("#calendar").weekCalendar("formatDate", new Date(end), "c"),
"title":title,
"body":deets
};
jsonArray[i] = jsonObj;
}
alert($.toJSON(jsonArray)); // Defined!
return ($.toJSON(jsonArray));
} else {
}
}
});
}
Any idea what I'm missing here?
function getEventData() {
function local() {
console.log(42);
return 42;
}
local();
}
Your missing the fact that the outer function returns undefined. And that's why your answer is undefined.
Your also doing asynchronous programming wrong. You want to use callbacks. There are probably 100s of duplicate questions about this exact problem.
Your getEventData() function returns nothing.
You are returning the JSON object from a callback function that's called asynchronously. Your call to $.ajax doesn't return anything, it just begins a background XMLHttpRequest and then immediately returns. When the request completes, it will call the success function if the HTTP request was successful. The success function returns to code internal in $.ajax, not to your function which originally called $.ajax.
I resolved this by using callbacks since AJAX is, after all. Once the data is retrieved it is assigned to a global variable in the callback and the calendar is refreshed using the global variable (datas).
$(document).ready(function() {
// Declare variables
var $calendar = $('#calendar');
datas = "";
set = 0;
// Retrieves event data
var events = {
getEvents : function(callback) {
var dataString = "minDate="+ minDate/1000 + "&maxDate=" + maxDate/1000;
$.ajax({
type: "POST",
url: "busker_ops.php",
data: dataString,
dataType: "json",
success: function(data) {
if(data != null) {
var jsonArray = new Array();
var jsonObj = {};
for(var i = data.length - 1; i >= 0; --i) {
var o = data[i];
var set_id = o.set_id;
var start = o.startOrig;
var end = o.endOrig;
var title = o.title;
var deets = o.deets;
jsonObj =
{
"id":parseInt(set_id),
"start":$("#calendar").weekCalendar("formatDate", new Date(start), "c"),
"end":$("#calendar").weekCalendar("formatDate", new Date(end), "c"),
"title":title,
"body":deets
};
jsonArray[i] = jsonObj;
}
//alert($.toJSON(jsonArray));
callback.call(this,jsonArray);
} else {
}
}
});
}
}
$calendar.weekCalendar({
data : function(start, end, callback) {
if(set == 1) {
callback(datas);
//alert(datas.events);
}
}
});
// Go get the event data
events.getEvents(function(evented) {
displayMessage("Retrieving the Lineup.");
datas = {
options : {},
events : evented
};
set = 1;
$calendar.weekCalendar("refresh");
});
});

How to acces a global variable in a callback object in javascript YUI without use window.myvariable?

I have this :
var MyObject = function(){
this.url = "monurl";
this.mavar = "";
this.Load = function(){
var callback = {
success: function(o){
mavar = o.responseXML.getElementsByTagName("montag")[0].firstChild.nodeValue;
}
}
YAHOO.util.Connect.asyncRequest('GET',url,callback);
} }
the mavar variable is not accessible. How can I do this ?
I believe you can set a scope param to the callback. So you should be able to do something like the following.
var MyObject = function(){
this.url = "monurl";
this.mavar = "";
this.Load = function(){
var callback = {
success: function(o){
this.mavar = o.responseXML.getElementsByTagName("montag")[0].firstChild.nodeValue;
},
scope: this
}
YAHOO.util.Connect.asyncRequest('GET', this.url, callback);
} }
You could also do it like this:
var MyObject = new function(){
this.url = "monurl";
this.mavar = "";
this.Load =
(function(that){
return function(){
var callback = {
success: function(o){
that.mavar = o.responseXML.getElementsByTagName("montag")[0].firstChild.nodeValue;
}
}
YAHOO.util.Connect.asyncRequest('GET',url,callback);
}
})(this);
};
In my object, I add a variable that's reference the this :
var selfMyObject = this;
and I replace the this.mavar to selfMyObject.mavar in success callback and it's work fine.
Save the this variable:
var MyObject = function() {
this.url = "monurl";
this.mavar = "";
this.Load = function() {
var me = this;
var callback = {
success: function(o) {
me.mavar = o.responseXML.getElementsByTagName("montag")[0].firstChild.nodeValue;
}
}
YAHOO.util.Connect.asyncRequest('GET',url,callback);
}
}
The best way to handle this is to let YUI do your scope correction, since support is built in. Here's the docs page telling you how to to do it. http://developer.yahoo.com/yui/connection/#scope
var MyObject = function() {
this.url = "monurl";
this.mavar = "";
this.Load = function() {
var callback = {
success: function(o){
this.mavar = o.responseXML.getElementsByTagName("montag")[0].firstChild.nodeValue;
},
scope: this
}
YAHOO.util.Connect.asyncRequest('GET', url, callback);
}
}

Categories

Resources