I'm using a parent to pass a multi-dimensional array to a child. Structure of the array, named projectPositions is as follows (with example data):
projectPositions[0][0] = 1;
projectPositions[0][1] = 5;
projectPositions[0][2] = '1AD';
projectPositions[0][3] = 'User name';
I need to take this inherited array and turn it into an arrayCollection so that I can use it as a dataProvider. Currently, my init function (which runs onCreationComplete) has this code in it to handle this task of array -> arrayCollection:
for (var i:int = 0; i < projectPositions.length; i++)
{
tempObject = new Object;
tempObject.startOffset = projectPositions[i][0];
tempObject.numDays = projectPositions[i][1];
tempObject.role = projectPositions[i][2];
tempObject.student = projectPositions[i][3];
positionsAC.addItemAt(tempObject, positionsAC.length);
}
Then, during a repeater, I use positionsAC as the dataprovider and reference the items in the following way:
<mx:Repeater id="indPositions" dataProvider="{positionsAC}" startingIndex="0" count="{projectPositions.length}">
<components:block id="thisBlock" offSet="{indPositions.currentItem.startOffset}" numDays="{indPositions.currentItem.numDays}" position="{indPositions.currentItem.role}" sName="{indPositions.currentItem.student}" />
</mx:Repeater>
This all works fine and returns the desired effect, but the load time of this application is around 10 seconds. I'm 99% sure that the load time is caused by the array -> arrayCollection for loop. Is there an easier way to achieve the desired effect without having to wait so long for the page to load?
The issue your having loading items could be because you are using a repeater instead of a list class.
With a repeater, there will be a block created in memory, and drawn on the screen. So, if you have 100 items in your array, then 100 blocks will be created. this could slow down both initial creation and the overall app.
A list based class focuses on a technique called renderer recycling; which means only the displayed elements are created and rendered on the screen. So, depending on settings, you'd usually have 7-10 'block' instances on the screen, no matter how many items you have in your array.
change
positionsAC.addItemAt(tempObject, positionsAC.length);
to
positionsAC.addItem(tempObject);
addItemAt is causing a reindex of the collection which can greatly slow down the collection.
[EDIT]
Put this trace statement before and after the loop
take the output and subtract one from the other and that will show how many milliseconds the loop has run.
var date:Date = new Date( );
trace( date.getTime())
Related
I have created many, let's say three ObjectStores inside a defined and versioned IndexedDB schema.
I need to populate all of them. To do so, I created an object which stores both name end endpoint (where it gets data to populate).
Also to avoid error when trying to fill objectstores already populated, I use the count() method to ... count key inside the objectstore and if there are 0 key, then populates, else reads.
It works perfect if I execute on a one by one basis, that is instead of using a loop, declare and execute each one of the three objectstores.
However when invoking the function to populate each storage inside a loop, I get the following error message for the last two objectstores to be populated:
Failed to read the 'result' property from 'IDBRequest': The request
has not finished. at IDBRequest.counts.(anonymous function).onsuccess
Here is the code:
// object contains oject stores and endpoints.
const stores = [
{osName:'user-1', osEndPoint:'/api/1,
{osName:'user-2', osEndPoint:'/api/2},
{osName:'user-3', osEndPoint:'/api/3}
];
// open db.
var request = indexedDB.open(DB_NAME, DB_VERSION);
// in order to dynamically create vars, instantiate two arrays.
var tx = [];
var counts = [];
var total = [];
// onsuccess callback.
request.onsuccess = function (e) {
db = this.result;
for(k in stores) {
tx[k] = db.transaction(stores[k].osName).objectStore(stores[k].osName);
counts[k] = tx[i].count();
counts[k].onsuccess = function(e) {
total[k] = e.target.result;
// if the counting result equals 0, then populate by calling a function that does so.
if (total[k] == 0) {
fetchGet2(stores[k].osEndPoint, popTable, stores[k].osName); //
} else {
readData(DB_NAME, DB_VERSION, stores[0].osName);
}
};
} // closes for loop
}; // closes request.onsuccess.
The fetchGet2 function works well inside a loop, for example the loop used to create the objectstores, and also has been tested on a one by one basis.
It looks like an async issue, however I cannot figure how to fix the problem which is to be able to populate existing objectstores dynamically, avoiding to populate filled objectsores and only filling empty ones.
Indeed testing without the count issue, but inside the loop works perfect, or with the count but without loop.
At the moment and when logging counts[k], It only logs data for the last member of the object.
Thanks in advance, I'm coding with vanilla js, and I'm not interested in using any framework at all.
Yes, this looks like an issue with async. For loops iterate synchronously. Try writing a loop that does not advance i until each request completes.
I've been trying to learn swift for a few days now, and all tutorials I've found had had a specified number of SKNodes. I'm trying to programmatically add new instances to an array nodeList and add them to the scene, because I want each of them to execute some code periodically. This is my current version of code for adding more objects:
if (last_created < 0) {
//Some other code here
for i in 0...3 {
self.nodeList.append(self.backObject);
var x_current = CGFloat(Float(arc4random())/4294967296.0 * Float(x_range) + Float(x_min));
var y_current = CGFloat(Float(y_min) - Float(y_range));
self.nodeList[self.nodeList.count-1].position = CGPoint(x: x_current, y: y_current);
self.addChild(self.nodeList[self.nodeList.count-1]);
}
}
Attempt to execute this raises an exception:
Attemped to add a SKNode which already has a parent
I assume that every item in my nodeList array is seen as the same object, rather than separate instances. However, I don't know how to fix the problem. How should I have done this?
Thanks for your help.
You are adding self.backObject to the array multiple times, so it is being added to the scene more than once, causing the error. You should create a new instance of the node within the loop and add that to the array.
I need is to dynamically add the points I’ve received from a forex provider to s Shield UI Chart. According to the documentation, there isn’t the possibility for dynamically adding of points At least there is no such method, something like: AddPoint or similar.
How can I still achieve a web page using Shield UI Chart, which to constantly show a couple of exchange rates?
You are right, that there is no addPoints method of the Shield UI Chart. However we can add the incoming data values to an array instead. You might find useful following code:
We need some arrays- as many as we need to show.
var EURUSD = new Array();
var USDCAD = new Array();
var GBPUSD = new Array();
In the body of the function, that will actually display the data we will have the following code:
EURUSD[EURUSD.length] = parseFloat(data.ticks.EURUSD);
USDCAD[USDCAD.length] = parseFloat(data.ticks.USDCAD);
GBPUSD[GBPUSD.length] = parseFloat(data.ticks.GBPUSD);
it will actually put the new data to the designated arrays. You can note, that each time data is received, it has been added to the last index of each array:
EURUSD.length
Since we don’t want our arrays to grow too large, it is good to specify how many points we need to keep. Once that limit is reached, we remove the oldest point:
if (EURUSD.length > 50)
EURUSD = EURUSD.splice(1, 49);
if (USDCAD.length > 50)
USDCAD = USDCAD.splice(1, 49);
if (GBPUSD.length > 50)
GBPUSD = GBPUSD.splice(1, 49);
At the end we need to recreate the chart, referencing the appropriate container:
var containter = $("#EURUSDChart").swidget();
containter.destroy();
and than create the chart again.
So, I have a LoaderMax instance loading images from various URLs. I want to add all loaded images to an array.
Here's my code:
var photosArray:Array = new Array(5);
var imageLoadingQueue:LoaderMax = new LoaderMax({name:"mainQueue", onComplete:completeHandler});
for (var g:uint=0; g<5; g++)
{
imageLoadingQueue.append(new ImageLoader("/img" + g + ".jpg", {name:"photo", container:photosArray[g], noCache:false, smoothing:true, width:126, height:126, scaleMode:"proportionalOutside"}));
}
imageLoadingQueue.load();
private function completeHandler(e:LoaderEvent):void
{
trace("finished loading pictures!");
//the next two lines will return an error (saying that photosArray[1] is null)
stage.addChild(photosArray[1]);
photosArray[1].x = 250;
}
A few problems:
If I set the container of the image being loaded to the Array, it won't work. I'm not being able to access the image inside the array because it says it's null.
If I set the container of the image being loaded to "this" (using the container property when appending a new ImageLoader) and, on the completeHandler, set my array equal to event.target.content, it kinda works (but it's not the ideal). The problem is that, by doing so, the images are appearing on the stage as they are loaded, and I do no want them to do so.
Any help would be heavily appreciated.
Thanks!!
David is correct, but I also wanted to mention that the LoaderMax's "content" is actually an array of all of its children's content, so you could just use that for simplicity. Keep in mind that ImageLoaders automatically create a Sprite (technically called a "ContentDisplay") to drop the image into so you probably don't need to create ANOTHER Sprite (a container for the container).
var photos:Array = imageLoadingQueue.content;
stage.addChild(photos[1]);
The other nice thing is that it creates the ContentDisplay Sprites immediately, even before any content is loaded into them, so you can place them and size them however you want while (or before or after) loading occurs.
The container needs to be a DisplayObjectContainer. ImageLoader will try to add the image to the container using addChild(), so obviously this won't work with an empty array. Create a new Sprite for each image and add it into the array first:
for (var g:uint=0; g<5; g++)
{
photosArray[g] = new Sprite();
imageLoadingQueue.append(new ImageLoader("/img" + g + ".jpg", {name:"photo", container:photosArray[g], noCache:false, smoothing:true, width:126, height:126, scaleMode:"proportionalOutside"}));
}
I've imported several images into an actionScript 3 document. I've turned them all into symbols (movie clips) and given them instance names to reference from ActionScript.
Ok, so I'm putting the instances into an array so I can loop through them easily, but for some reason, whenever I'm putting in the instance name, I do a trace on the value in the array and it's giving me the symbol object back, rather than the instance object.
Basically trying to loop through the array to make each instance's visibility = false
Here's a sample:
var large_cap_extrusion_data: Array = new Array();
large_cap_extrusion_data[0] = large_cap_extrusion_menu_button;
large_cap_extrusion_data[1] = extrusion_border_large_cap
large_cap_extrusion_data[2] = "Large Cap";
large_cap_extrusion_data[3] = large_cap_main_menu_button;
var extrusion_data: Array = new Array();
extrusion_data[0] = large_cap_extrusion_data;
trace(extrusion_data[0][0]);
The traces gives:
[object large_cap_menu_button]
(the parent symbol)
rather than:
"large_cap_extrusion_menu_button"
I'd be very grateful if someone could tell me where I'm going wrong...
when you trace and object, by default it describes it type. What you want is the "name" property of the object.
Try this:
trace(extrusion_data[0][0].name);
that should give you the instance nema of the large_cap_menu_button rather than the class description. Either way, you have the right object I bet.