I have a function in my processing.js file that calls for an AJAX script to return an array with which I want to define some simple starting variables for my code. I want this function to complete before any other part of the code that comes after it is executed.
When i run my code both the alerts in the setup() phase and the first alert in the draw() return "undefined" while the next iterations in the draw() phase return the actual array I need.
The processing code:
var loadArray;
setup() {
loadArray = new Array();
js_GetArray(function(data) {
loadArray = data;
});
alert(loadArray[1]);
alert(loadArray[2]);
}
void draw()
{
alert(loadArray[k]);
k++;
}
The AJAX:
<!-- Read the vars numbers from the mysql database and return them -->
<script language="JavaScript" type="text/javascript">
function js_GetArray(callback) {
$.get( "load.php", function( actiondata ) {
var obj = JSON.parse(actiondata);
callback(obj);
});
}
</script>
Is there a way to force the program to complete the js_GetArray call before moving on to the rest of the code?
If it is during loading of the page, then what about using a flag as indication that the call has returned?
var loadArray;
var isloaded = false;
setup() {
loadArray = new Array();
js_GetArray(function(data) {
loadArray = data;
isloaded = true;
alert(loadArray[1]);
alert(loadArray[2]);
});
}
void draw()
{
if(isloaded)
{
alert(loadArray[k]);
k++;
}
}
EDIT:
I have moved the alerts inside the callback function.
As an alternative answer to the one given, I've covered this on the processingjs.org website extensively, so you probably want to give that a read: http://processingjs.org/articles/PomaxGuide.html#interface
Related
I need to do some API call and also DB manipulation during rendering of messages for a function.
I have these long function, let's call it alongFunction
function longFunction(message, item) {
var win = lib.gui.window.get(id);
var msg = message.msg;
var id = message.id;
var direction = message.direction;
//inside are basically some DOM manipulation
//around 10 lines here
//and also there are rendering/misc code
//around 10 lines here
//then we are rendering some messages here:
var msgDiv = $('<div>'), msgTsDiv = $('<div>');
msgDiv.addClass('chat '+direction);
msgDiv.attr('id', id);
if(direction == 'in') {
//I need to add a hook here to do API call, but it takes some time
msgDiv.html('<div class="message in">'+message+'</div>');
} else {
msgDiv.html('<div class="message out">'+message+'</div>');
}
//NEW CODE ADDED HERE: Check below pls
//and because JS is async, it just passes these codes
//around 50 codes for manipulation etc...
if(message.isReceived()) {
msgDiv.addClass('received');
}
//and some other stuff here...
}
I added at the NEW CODED ADDED HERE these:
function longFunction(message, item) {
var win = lib.gui.window.get(id);
var msg = message.msg;
var id = message.id;
var direction = message.direction;
//inside are basically some DOM manipulation
//around 10 lines here
//and also there are rendering/misc code
//around 10 lines here
//then we are rendering some messages here:
var msgDiv = $('<div>'), msgTsDiv = $('<div>');
msgDiv.addClass('chat');
msgDiv.attr('id', id);
//only translating message coming in
if(direction == 'in') {
getTranslatedMessage(message).then(function(newMessage){
//I need to add a hook here to do API call, but it takes some time
msgDiv.html('<div class="message in">'+newMessage+'</div>');
}).catch(function(error){
if(error) {
msgDiv.html('<div class="message">'+message+'<br>'+error+'</div>');
} else {
msgDiv.html('<div class="message in">'+message+'</div>');
}
});
} else {
msgDiv.html('<div class="message out">'+message+'</div>');
}
//end of translation - UPDATE
//and because JS is async, it just pass these codes
//around 50 codes for manipulation etc...
if(message.isReceived()) {
msgDiv.addClass('received');
}
//and some other stuff here...
}
UPDATE:
I have tried
putting everything into one big callback = but it is not returning any result.
repeat the remaining code by copy-pasting it into the callback and outside = the message printed is not in proper sequence (this function is called in a loop)
Note: The function is a bit long, so I just made a simple version for it
Important: This function is being called in a loop.
Thank you in advance!
I have two JS files, base_player.js and station.js.
I have some logic in base_player.js that needs access to a value that comes from station.js. While the var is 'global', it is wrapped in a namepace mm.Station. The value I need is a UUID of a selected station:
mm.Station = function($el) {
"use strict";
if (_.isUndefined($el)) {
return;
}
var self = mm.EventEmitter();
var $actions;
self.uuid = $el.attr("data-uuid");
.........
I feed any selected station with songs in batches at a certain point in a queue. This logic all happens in base_player.js.
I want to get the UUID from station.js to use in this GET in base_player.js:
mm.BasePlayer = function ($el) {
........
function feedSelectedStation(uuid) {
if(_.isUndefined(uuid)){
return false;
}
$.get('/feed-station/' + uuid)
.done(function (data) {
console.log('feedSelectedStation');
if(!_.has(data, "list")){ return; }
self.queue = self.queue.concat(data.list);
});
}
.........
I don't write much Javascript so I'm a bit unsure how to achieve this. Any pointers appreciated.
I'm trying to put the data read from the database in a variable. I have tryed many things, including a callback function, but nothing looks to work when the process is outside of the "opencursor().onsuccess" function scope.
The "Alert 1" show the result correctly, but "Alert 2" and "Alert 3" don't.
I'm calling the 'main()' function from HTML code.
I'm really frustrated, because I have been mining internet searching for the solution without any positive result.
Can anybody help me, please?
Thanks a lot.
var data=[];
function kkeyget(t1, db_name, db_version)
{
var request = indexedDB.open(db_name, db_version);
request.onerror=function()
{
alert("Error");
}
request.onsuccess=function(event)
{
var db=this.result;
var trans = db.transaction(t1, "readonly");
var objectStore = trans.objectStore(t1);
objectStore.openCursor().onsuccess = function(event)
{
var cursor = event.target.result;
if (cursor)
{
data.push(cursor.value);
//Alert 1:
alert(data[0].id);
cursor.continue();
}
else alert("No more entries!");
};
}
//Alert 2:
alert(data[0].id);
}
function main()
{
kkeyget("agenda", "example_db", 1);
//Alert 3:
alert(data[0].id);
}
Correct. Because all indexedDB actions are asynchronous, your code will run:
alert 2 // undefined
alert 3 // undefined
alert 1 // correct
In order to get this closer to a synchronous action, you need to have it call a new function after it's done collecting data. Where your alert("No more entries!") is.
Instead of trying to return a key, pass in a custom callback function that takes the retrieved key as its argument.
// Your old function slightly modified
function kkeyget(t1, db_name, db_version, callback, fallback) {
// ... yada yada yada
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
callback(cursor.value);
} else {
fallback();
}
}
}
// Now in your calling code:
kkeyget('a','b',1, function(id) {
// Do something with the 'id'
// here in this anonymous function callback
}, function() {
// Do something here to indicate no match
});
I ran into a roadblock when developing my website. I need it to pull a text file in the same directory and return each line as an array.
So I did my research and came up with a function that seemed simple enough. However when I alert(theArray); it returns as undefined. What am I doing wrong?
function pullText(x)
{
var fullText = [];
fileReturn=new XMLHttpRequest();
fileReturn.onreadystatechange=function()
{
if (fileReturn.readyState==4 && fileReturn.status==200)
{
entireTextFile = fileReturn.responseText;
// alert(entireTextFile); works as expected here
lines = fileReturn.responseText.split("\n");
// alert(lines); works as expected here
fullText = lines;
}
}
// alert(fullText); does not work.
fileReturn.open("GET",x,true);
fileReturn.send();
return fullText;
}
It won't work that way because AJAX is A-synchronous. You should pass a callback handler and call that once the document is ready.
function pullText(x, callback)
{
// var fullText = []; not necessary
fileReturn=new XMLHttpRequest();
fileReturn.onreadystatechange=function()
{
if (fileReturn.readyState==4 && fileReturn.status==200)
{
entireTextFile = fileReturn.responseText;
// alert(entireTextFile); works as expected here
lines = fileReturn.responseText.split("\n");
// alert(lines); works as expected here
callback(lines);
}
}
// alert(fullText); does not work.
fileReturn.open("GET",x,true);
fileReturn.send();
}
pullText(whatever, function(lines) {
// use lines here
});
Thank you for taking the time to help me.
I am writing a game where an animated train icon moves along a given path to a destination, pausing at waypoints along the way. This is intended to give the impression of animation.
The game is coded in Facebook Javascript. I need to find a way to make the train icon pause for 1 second before moving on to the next waypoint. I hoped to find a function that would allow me to pause script execution for one second, but nothing like that seems to exist in JS. So I tried setTimeout, but my primary problem with this is twofold:
I need to pass an array into the callback function as an argument, and I can't figure out how to make setTimeout do this.
I finally succeeded in using setTimeout to execute my train animation code for 5 waypoints (I overcame the issue in 1 by using global variables). Unfortunately, it appears that all five calls to setTimeout got queued almost simultaneously, which resulted in waiting one second for the first setTimeout to fire, thenn they all fired at once ruining the illusion of train animation.
I've been battling this problem for six hours straight. It would be wonderful if someone could help me find a solution. Thanks!
Here's the code:
function myEventMoveTrainManual(evt, performErrorCheck) {
if(mutexMoveTrainManual == 'CONTINUE') {
var ajax = new Ajax();
var param = {};
if(evt) {
var cityId = evt.target.getParentNode().getId();
var param = { "city_id": cityId };
}
ajax.responseType = Ajax.JSON;
ajax.ondone = function(data) {
var actionPrompt = document.getElementById('action-prompt');
actionPrompt.setInnerXHTML('<span><div id="action-text">'+
'Train en route to final destination...</div></span>');
for(var i = 0; i < data.length; i++) {
statusFinalDest = data[i]['status_final_dest'];
//pause(1000);
gData = data[i];
setTimeout(function(){drawTrackTimeout()},1000);
if(data[i]['code'] == 'UNLOAD_CARGO' && statusFinalDest == 'ARRIVED') {
unloadCargo();
} else if (data[i]['code'] == 'MOVE_TRAIN_AUTO' || data[i]['code'] == 'TURN_END') {
//moveTrainAuto();
} else {
// handle error
}
mutexMoveTrainManual = 'CONTINUE';
}
}
ajax.post(baseURL + '/turn/move-train-final-dest', param);
}
}
function drawTrackTimeout() {
var trains = [];
trains[0] = gData['train'];
removeTrain(trains);
drawTrack(gData['y1'], gData['x1'], gData['y2'], gData['x2'], '#FF0', trains);
gData = null;
}
Typically this would be done by creating an object (say called myTrain) that has all its own data and methods, then call a myTrain.run mehod that looks to see where the train is. If it's between two stations, it calls itself with setTimeout and say a 50ms delay. When it reaches a station, it calls itself in 1000ms, creating a 1 second pause at the station.
If you queue the setTimeouts all at once, you run the risk of them all being delayed by some other process, then all running at once.
Hey, bit of fun (careful of wrapping). Needed a bit of practice with good 'ole prototype inheritance:
<!-- All the style stuff should be in a rule -->
<div style="position: relative; border: 1px solid blue;">
<div id="redTrain"
style="width:10px;height:10px;background-color:red; position:absolute;top:0px;left:0px;"></div>
</div>
<script type="text/javascript">
// Train constructor
function Train(id) {
this.element = document.getElementById(id);
this.timerId;
}
// Methods
// Trivial getPos function
Train.prototype.getPos = function() {
return this.element.style.left;
}
// Trivial setPos function
Train.prototype.setPos = function(px) {
this.element.style.left = parseInt(px,10) + 'px';
}
// Move it px pixels to the right
Train.prototype.move = function(px) {
this.setPos(px + parseInt(this.getPos(),10));
}
// Recursive function using setTimeout for animation
// Probably should accept a parameter for lag, long lag
// should be a multiple of lag
Train.prototype.run = function() {
// If already running, stop it
// so can interrupt a pause with a start
this.stop();
// Move the train
this.move(5);
// Keep a reference to the train for setTimeout
var train = this;
// Default between each move is 50ms
var lag = 50;
// Pause for 1 second each 100px
if (!(parseInt(this.getPos(),10) % 100)) {
lag = 1000;
}
train.timerId = window.setTimeout( function(){train.run();}, lag);
}
// Start should do a lot more initialising
Train.prototype.start = function() {
this.run();
}
// Stops the train until started again
Train.prototype.stop = function() {
if (this.timerId) {
clearTimeout(this.timerId);
}
}
// Set back to zero
Train.prototype.reset = function() {
this.stop();
this.setPos(0);
}
// Initialise train here
var myTrain = new Train('redTrain');
</script>
<p> </p>
<button onclick="myTrain.start();">Start the train</button>
<button onclick="myTrain.stop();">Stop the train</button>
<button onclick="myTrain.reset();">Reset the train</button>
To pass arguments, this might help you:
setTimeout(function() {
(function(arg1, arg2) {
// you can use arg1 / arg2 here
})('something', 123);
}, 1000);
Or, if you use a defined function:
setTimeout(function() {
someFunction('something', 123);
}, 1000);
It basically starts a timeout; after one second the function is invoked with the specified arguments.
How about using OO principles to simplify the problem? Create an "object" Train which has the following methods:
//train obj
function Train(){
this.isOnWaypoint = function(){
return calculateIsWayPoint()
}
}
//main logic
var train = new Train()
var doneWaiting = false
var doneWaitingTimeout = undefined
var gameLoop = setInterval(1000,function(){
...
if(train.isOnWaypoint() && !doneWaiting){
if(doneWaitingTimeout == undefined){
setTimeOut(5000,function(){
doneWaiting = true
doneWaitingTimeout = undefined
})
}
}
...
})
Here's the solution I finally came up with:
function drawTrackTimeout() {
if(gData != null && gIndex < gData.length) {
var trains = [];
trains[0] = gData[gIndex]['train'];
removeTrain(trains);
drawTrack(gData[gIndex]['y1'], gData[gIndex]['x1'], gData[gIndex]['y2'], gData[gIndex]['x2'], '#FF0', trains);
statusFinalDest = gData[gIndex]['status_final_dest'];
if(statusFinalDest == 'ARRIVED') {
unloadCargo();
} else if (gData[gIndex]['code'] == 'MOVE_TRAIN_AUTO' || gData[gIndex]['code'] == 'TURN_END') {
//moveTrainAuto();
} else {
// handle error
}
gIndex++;
} else {
clearInterval(gIntid);
gIntid = null;
gData = null;
gIndex = 0;
}
}
function myEventMoveTrainManual(evt, performErrorCheck) {
//debugger;
if(mutexMoveTrainManual == 'CONTINUE') {
var ajax = new Ajax();
var param = {};
if(evt) {
var cityId = evt.target.getParentNode().getId();
var param = { "city_id": cityId };
}
ajax.responseType = Ajax.JSON;
ajax.ondone = function(data) {
var actionPrompt = document.getElementById('action-prompt');
actionPrompt.setInnerXHTML('<span><div id="action-text">'+
'Train en route to final destination...</div></span>');
gData = data;
gIndex = 0;
gIntid = setInterval(function(){drawTrackTimeout()},1000);
}
ajax.post(baseURL + '/turn/move-train-final-dest', param);
}
}