I have the following code to implement Observable Memory Store
var inventory = [
{name:"shoes", quantity:10, category:"sales"},
{name:"clothes", quantity:5, category:"sales"},
{name:"hats", quantity:2, category:"sales"},
{name:"shirts", quantity:20, category:"sales"}
];
var inventoryStore = new Memory({data:inventory, idProperty: "name"});
var observer = new Observable(inventoryStore);
results = observer.query({});
results.observe(function(item, removedIndex, insertedIndex) {
if(removedIndex > -1) {
console.log("removed");
}
if(insertedIndex > -1) {
console.log("added");
}
console.log("Listened");
}, true);
inventoryStore.put(someObject);
Interestingly, the code does not listen to the changes made in inventoryStore. I expected it to call observe() method whenever something happens in the inventoryStore but it does not. Instead, if I put object in the observer not inventoryStore then it listens.
If I change the code like the follow
var inventoryStore = new Observable(Memory({data:inventory, idProperty: "name"}));
results = inventoryStore.query({});
inventoryStore.put(someObject);
then it works. This is frustrating that even I followed exact code from the documentation and it does not work.
The reason why I have to use the first code block (putting object in inventoryStore not in observer) is that some of my object can't be stored in Observable Memory but only in Memory.
Any advice will be appreciated :)
After hours of testing, it turns out that to observe changes in Memory Store, you have to add / remove / update objects through Observable object not through the Memory.
This means you have two options to implement this.
var inventoryStore = new Memory({data:inventory, idProperty:"name"});
var observer = new Observable(inventoryStore);
results = observer.query({});
observer.put(someObject);
or
var inventoryStore = new Observable(new Memory({data:inventory, idProperty:"name"});
results = inventoryStore.query({});
inventoryStore.put(someObject);
This may seem obvious but I was confused following the tutorial under this link.
http://www.tulek.org/2011/04/14/dojo-memory-and-observable-classes/
In addition,
observer.setData(another Inventory);
does not fire the observe() method but just change data store in the observer. This causes mismatching data store between Observable and Memory Store since Memory Store still has the original inventory set.
The reason why some of my object couldn't be stored in Observable was that I used dojo/calendar/Calendar and it had a reference to some of the objects from the Memory that call some weird method due to property name mismatched.
I hope none of you people suffer from this matter. :)
Although this post is 2 years old, i really benefit from it, because i suffered the same problem. But my fault was to set the overwrite flag as second param when calling the observe method (facepalm).
So if any of you stick on this problem nevertheless, make sure to set the includeObjectUpdates param.
resultSet.observe(listener, includeObjectUpdates);
Bye.
Related
I have seen multipath update example. But before updating any data i have to push it at first place for which i was wondering if there is something called as multipath push?
I want to simultaneously push data under different set of nodes.
eg: Firebase scheme
-Examinations
- pushIdLk12203425
- pushIdML0124245
-RightChoices
- pushIdLk12203425
- pushIdML0124245
-Questions
- pushIdLk12203425
- pushIdML0124245
When i push value under examination node, same values or different values as per my backend architecture have to be pushed under RightChoices and Questions Node. Right now i am doing this using .then callback approach.
I push data under Examinations and then in its .then callback i push in RightChoice and Questions node.
But my concern is what if user closes the app and data just reaches Examinations node and never reaches RightChoices and Questions Node.
I am trying to figure out a better way of having data consistency.
Thanks.
Note: RightChoices and Questions are kept under different nodes for having a better security architecture and i cannot change the schema.
Would be grateful if somebody can help me out. Thanks.
I think you are looking for .update()
Have a look here: https://firebase.google.com/docs/database/web/read-and-write#update_specific_fields:
function writeMultipath(pushID1, pushID2) {
var data = {
id1: pushID1,
id2: pushID2
};
// Write the new data simultaneously to your DB-locations
var updates = {};
updates['/Examinations/'] = data;
updates['/RightChoices/'] = data;
updates['/Questions/'] = data;
return firebase.database().ref().update(updates);
}
In my project I need to save the data to .txt or .xml or .json file. I could not find any answer from vis.js website/issues blog. It might be simple, do not know. Really helpful if anyone help me out with example code. Thank you so much in advance.
function saveData(data,callback) {
data.id = document.getElementById('node-id').value;
data.label = document.getElementById('node-label').value;
clearPopUp();
callback(data);
}
If I understand you correctly, you are looking for a way to save data and options of a graph. In my graph editor adaptation for TiddlyWiki Classic I use the following method to extract data (the full implementation can be found in the repo, see config.macros.graph.saveDataAndOptions, here's a simplified one):
config.macros.graph.saveDataAndOptions = function(network,newOptions) {
newOptions = newOptions || {};
// get nodes and edges
var nodes = network.body.data.nodes._data; // contains id, label, x,y, custom per-node options and doesn't contain options from options.nodes; presumably contains option values set when network was created, not current ones (it is so for x,y)
// no suitable getter unfortunately
var edges = network.body.data.edges._data; // map; for edges to/from? certain node use network.getConnectedNodes(id)
// network.body.data.edges._data is a hash of { id: , from: , to: }
// get node positions, options
var positions = network.getPositions(), // map
options = // get options stored previously
// merge newOptions into options
for(var nodeId in nodes) {
// nodes[nodeId].x is the initial value, positions[nodeId].x is the current one
if(positions[nodeId]) { // undefined for hidden
nodes[nodeId].x = positions[nodeId].x;
nodes[nodeId].y = positions[nodeId].y;
}
storedNode = copyObjectProperties(nodes[nodeId]);
storedNodes.push(storedNode);
}
//# do whatever you need with storedNodes, edges and options
// (pack them with JSON.stringify, store to a file etc)
};
However, while this works ok for storing data, this only helps to save options passed for storing explicitly which can be not very nice for some cases. I use this method in manipulation helpers and on dragEnd (network.on("dragEnd",this.saveToTiddlerAfterDragging), config.macros.graph.saveToTiddlerAfterDragging = function(stuff) { config.macros.graph.saveDataAndOptions(this,{ physics: false }); };). I haven't recieved any better suggestions, though.
If you need to get data and options reactively and setting such helper to handle certain edit events can't solve your problem, then I suggest wrapping nodes, edges and options as vis.DataSet and save those when needed. This is related too.
To answer the question about events/other ways to use such methods. Here's how I use them:
I save data after drag&drop moving of nodes, this is done using an event handler. Namely, I introduced
config.macros.graph.saveToTiddlerAfterDragging = function(stuff) {
config.macros.graph.saveDataAndOptions(this,{ physics: false });
};
(when drag&drop is used, physics should be switched off, otherwise coordinates won't be preserved anyway) and then I use
network.on("dragEnd",this.saveToTiddlerAfterDragging);
so that changes are saved.
As for saving after adding/editing a node/edge, I apply saving not by an event (although it's nice thinking, and you should try events of DataSet, since there's no special graph events for that). What I do is I add an elaborated hijack to the manipulation methods. Take a look at the source I've linked after the
var mSettings = options.manipulation;
line: for each manipulation method, like options.manipulation.addNode I hijack it so that its callback is hijacked to call config.macros.graph.saveDataAndOptions in the end. Here's a simplified version of what I'm doing:
var nonSaving_addNode = options.manipulation.addNode;
options.manipulation.addNode = function(data,callback) {
// hijack callback to add saving
arguments[1] = function() {
callback.apply(this,arguments); // preserve initial action
config.macros.graph.saveDataAndOptions(network); // add saving
};
nonSaving_addNode.apply(this,arguments);
}
The thing is, addNode is actually called when the add node button is clicked; though, I'm using a customized one to create a popup and apply changes once user is happy with the label they chose.
In Screeps, I this code doesn't work:
var sources = creep.room.find(Game.FIND_SOURCES_ACTIVE);
It says this:
Cannot read property 'find' of undefined
I have been looking around and cannot find ANY other way to find sources.
Also I've noticed that most of other peoples code doesn't work and even the tutorial's code no longer works when put into the real game.
I can't be completely sure about your issue since I don't have your complete code to go off of but one issue could be that creepis not defined.
You need somewhere in your code to define creep such as a for loop to loop over each of your creeps in the game or room.
var roleMiner = require('role.miner') // role.miner being the module name for miner actions
for(var name in Game.creeps) {
var creep = Game.creeps[name];
//
// do whatever you wish with the current selected creep.
//
// most of the time you will call a module similar to what the tutorials suggest and put your actions for it in there
//
if(creep.memory.role == 'miner'){
roleMiner.run(creep); // passes the current selected creep to the run function in the module
}
}
So, in your roleMiner module you would have something that defines your miners actions.
var roleMiner = {
run: function(creep) {
// this one returns an array of the sources that are in the room with the creep
var sourcesRoom = creep.room.find(FIND_SOURCES);
// this one returns the source object which is closest to the creeps positon
var sourcesClose = creep.pos.findClosestByRange(FIND_SOURCES);
}
}
module.exports = roleMiner;
Hope this helps.
Screeps have some ... mechanism when sharing your data between each game tick.
If you store any thing in global Memory object, your data will lose all its prototype.
to restore your prototype use Object.setPrototypeOf(creep,Creep.prototype) or create new Creep object from your creep id.
I think what you are looking for is:
var sources = creep.pos.findClosestByRange(Game.SOURCES);
or
var sources = creep.pos.findClosestByPath(Game.SOURCES);
im a new player, not sure my code is efficient, i think the find method will be like this:
var sources = creep.room.find(FIND_SOURCES_ACTIVE)
creep will going to the active resource to harvester.
We trying send 500kb through ChromeWoker and get out of memory error in console.
This code:
let charArray= ctypes.ArrayType(ctypes.char);
let base641 = new charArray(9999999);
var {ChromeWorker} = Cu.import("resource://gre/modules/Services.jsm", null);
var chworker = new ChromeWorker(self.data.url("async.js"));
chworker.onmessage = function(e){
console.error(e.data);
};
chworker.postMessage(base641);
return error:
stack:"#undefined:undefined:undefined
CuddlefishLoader/options<.load#resource://gre/modules/commonjs/sdk/loader/cuddlefish.js:129:9
run#resource://gre/modules/commonjs/sdk/addon/runner.js:169:9
startup/<#resource://gre/modules/commonjs/sdk/addon/runner.js:113:7
Handler.prototype.process#resource://gre/modules/Promise-backend.js:863:11
this.PromiseWalker.walkerLoop#resource://gre/modules/Promise-backend.js:742:7"
What is undefined? Can we set pointer to the memory through ChromeWorker?
To pass a ctypes array, you'd take the address() and post that in a message and construct another pointer from that address on the other side. This works, but is rather nasty, of course. You'd also need to make sure that garbage collection does not collect stuff while the other side it still using it!
You might be better off using ArrayBuffer/typed arrays which you can pass directly, also from non-privileged code.
First things first: I'm not sure whether the information that I'm going to provide will be enough, I will happily add additional information if needed.
I'm serializing a complex structure into the JSON-Format, Field[i][0] is the "this"-reference to an object.
Firebug's Output on JSON.Stringify(myObj)
This is all fine and working as long as I keep it all JS. But now I have the requirement to serialize and send it to my backend to get the reference + computed information back.
Now how do I map back to the reference I had before? How do I bind this ref back to an Object?
This $$hash thing looks internal and proprietarish so I havent even bothered trying something like Object[$$hash] = ref or whatever.
This general idea probably seems pretty whack, but the result is returned asynchrously and I need an identifier to bind the new information back to the original object. Obviously I could just make up my own identifier for that, but I was wondering whether there's an option to solve it this way.
EDIT
The objects are created like this (likewise)
var arrayOfObj = []
arrayOfObj.push(new Object.With.SomeSettersAndGetters());
The Object has a method like
function GetRef(){
return this;
}
Which I'm using to keep a ID/Ref through my code.
Thank you!
Update
If you want to update a series of instances and make many Ajax requests, then you need to look at Ajax long polling and queueing techniques. You won't be able to preserve the reference, but regardless of what Ajax technique you use, make use of the below trick to preserve the reference.
Add long polling on top and you're good to go.
The idea is this:
Assume the server will respond in JSON format. If you need to refer to the original references, here's my two cents:
Update the exact references when the server replies. Say you have 10 instances of Something stored in an array. On a successful response, you use the methods in the Something class to update the specific instances in whatever way you want.
/**
* The array with something instances.
* #type {Array.<Something>}
*/
var instances = [];
/**
* The Ajax success function.
* #param {Event} event The event object.
*/
function ajaxSuccess(event) {
var response = event.target.getResponseText();
var actualResponse = JSON.parse(response);
for (var i = 0, len = actualResponse.length; i++) {
instances[i].setWhatever(actualResponse[i].whatever);
};
};
The above is a more procedural approach. If you want full blown OOP in JS, then you think in modular design patterns. Say you have a module that loads data into some place. Basically, everything related to that module is an instance property.
var myModule = function() {
this.whatever = 1;
};
myModule.prototype.loadMore = function() {
var request = new XMLHttpRequest(),
that = this; // store a reference to this.
request.send(); // etc
request.onreadystatechange = that.onSucess;
};
myModule.prototype.onSucess = function(event) {
var response = JSON.parse(event.target.getResponseText());
this.whatever = response.whatever;
};
var moduleInstance = new myModule();
myModule.loadMore();
// Now the scope is always preserved. The callback function will be executed in the right scope.
Let's assume on the backend side of things, you have a model class that mimics your client side JavaScript model. Say you want to update a reference inside a model that displays text. I use Scala on the backend, but look at the fields/properties and ignore the syntax.
case class Article (
title: String,// these are my DB fields for an Article.
punchline: String,
content: String,
author: String
);
// now assume the client is making a request and the server returns the JSON
// for an article. So the reply would be something like:
{"title": "Sample title", "punchline": "whatever", "content": "bla bla bla boring", "author": "Charlie Sheen"};
// when you do
var response = JSON.parse(event.target.getResponseText());
// response will become a JavaScript object with the exact same properties.
// again, my backend choice is irrelevant.
// Now assume I am inside the success function, which gets called in the same scope
// as the original object, so it refers TO THE SAME THING.
// the trick is to maintain the reference with var that = this.
// otherwise the onSuccess function will be called in global scope.
// now because it's pointing to the same object.
// I can update whatever I want.
this.title = response.title;
this.punchline = response.punchline;
this.content = response.content;
this.author = response.author;
// or I can put it all in a single variable.
this.data = response;
What you need to remember is that scope needs to be preserved. That's the trick.
When I do var that = this; I copy a reference to the model instance. The reference is remembered through higher-order, not current scope.
Then I tell the XMLHttpRequest object to call that.ajaxSuccess when it is complete. Because I used that, the ajaxSuccess function will be called in the scope of the current object. So inside the ajaxSuccess function, this will point to the original this, the same instance.
JavaScript remembers it for me it when I write var that = this;