reuse serialized reference to "this"-Keyword - javascript

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;

Related

Node.js how to pass variable reference so it's in callback functions scope

I'm trying to create a node.js app using the leaflet library, however the WMS I'm using uses Basic Authentication which isn't supported in leaflet so I've extended Tilelayer.WMS to grab the image with a seperate request and convert it to base64. This is all working correctly however I'm fairly new to node/javascript in general and have no idea how I'm supposed to pass a reference to my tile variable through so it's available in the later callback.
readerLoaded(reader) {
console.log(reader.target.result);
//want to be able to do something like this in here
tile.src = reader.target.result;
},
createTile (coords, done) {
var tile = document.createElement('img');
//Removed non-relevant code setting up header options etc
var reader = new FileReader();
reader.onload = this.readerLoaded;
http.get(url, options).subscribe(
m => {reader.readAsDataURL(m.blob());},
error => {console.log(error);}
);
return tile;
}
How do I pass a reference to the specific tile created in each createTile call so it's available in the subsequent readerLoaded call?
Also is there an efficient way to delay createTile returning until the readerLoaded callback has finished? I know if I was designing this myself it'd be a callback which was executed when it was ready however since I'm editing an existing library rewriting large parts of it seems like more effort than it's worth.
Thanks.
First off, you can't take an existing function definition like you show for readerLoaded() and "add" something to it's scope from within createTile(). That's just not how scope works in Javascript.
The usual way to make variables available within a function are to pass them as arguments or define them in the existing parent scope. Here's an example of passing as an argument.
readerLoaded(reader, tile) {
console.log(reader.target.result);
//want to be able to do something like this in here
tile.src = reader.target.result;
},
createTile (coords, done) {
var tile = document.createElement('img');
//Removed non-relevant code setting up header options etc
var reader = new FileReader();
reader.onload = (reader) => {
return this.readerLoaded(reader, tile);
}
http.get(url, options).subscribe(m =>{reader.readAsDataURL(m.blob());},
error=>{console.log(error);});
return tile;
}
If readerLoaded is going to be a method on an object, then you can't really define a temporaral variable such as tile in it's parent scope as there is no real Javascript syntax to do that. So, it appears your best option here is to pass it as an argument.

Can an object become 'stuck' inside another object (because its deep)?

This question is not specific to this particular scenario. The scenario could be concerning any complex/deep JavaScript object but for me to visualize the question I need a scene. Do not answer specifically on the supplied example - only cloning, scope and objects.
Brief Outline
If I have stored a websocket object inside an object, could I later move this websocket out of the storage object and put into another object? kind of like when you pop or splice an array, the array item is not only removed from the array but it's also returned to you (not obliterated but transferred / 'plucked from'). Or is the websocket object stuck/tied to the storage object {}? (If so, in what state would the object be in a lower scope?? What is it 'then'?)
Obviously:
//pseudo code
var finalobject = Object.assign({},storageobject.socket);
//not in nodejs? probably a bad idea anyway
var finalobject = storageobject.socket;
//only a shallow reference
delete storageobject.socket
finalobject.test = 'abc123';
// Obvious TypeError: Cannot set property..bla bla
what would I have though if?:
function lowerscope(x){return x;}
var sameobject=lowerscope(storageobject.socket);
is sameobject now dolly the sheep? a shallow reference or a deep reference? a copy?
My Question And The reason Why I think it's not a stupid question
If I first assign the socket in the storage object to the finalobject
then delete the storageobject.socket then I cant use the finalobect or set properties because that was just a shallow reference to what I just deleted.
So what exactly is going on if I pass the finalobject through a function like so? (again pseudo code)
var finalobject = storageobject.socket;
function appInit(mySocket) {
// do app stuff here with mySocket
// set up some functions...
return; // * come back out to main scope
}
appInit(finalobject);
delete storageobject.socket; // * what am I deleting??
Is the object cloned into appInit? Or does it live there as just another reference?
Example of my code flow (optional; you can skip this):
This part is (too) specific to my case and is here only in case someone asks to see code or 'needs' to understand why I ask.
I have put/created-reference-to my newly created (node.js ws) Websocket in another object:
var uid = '7657rrfdt6e6t'; //unique id
var socketsReference = {}; //main scope
socketServer.on('connection',function(mainSocket) {
var socketsGroup = {}; //local scope
mainSocket.uid = uid;
socketsGroup[1] = mainSocket;
socketsReference[uid] = socketsGroup;
socketsGroup[1].send('uid:' + uid);
So that is the main socket that is stored in the object. It has just sent its uid to the client so that it can set that as its uid property too.
Then next thing I do is connect the client to a secondary socket. For this I want the secondary socket to end up with the similar uid+'.s2' unique id as the main so what I do is connect the second socket then send the new 2nd connection a message from the client to the server which tells the server side socket the uid of the mainSocket
secondarySocket.on('message', function(data) {
this.uid = data.uid + '.s2';
socketsReference[data.uid][2] = this;
Later in the application I take the correct user specific socket group and inject it into the main application where the connected user is in his own scope.
var mySockets = socketsReference[my_uid]
appInit(mySockets);

(dojo) Observable cannot observe changes in Memory Store

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.

Javascript OOP events

I want to create an object that can parse a certain filetype. I've looked at some of the files in the File API and I want my object to work about the same. So basically, what I want is this:
A function, called CustomFileParser. I want to be able to use it as the following:
var customFileParser = new CustomFileParser();
customFileParser.parsed = paresed;
customFileParser.progress = progress;
customFileParser.parse(file);
function parsed(event){
//The file is loaded, you can do stuff with it here.
}
function progess(event){
//The file load has progressed, you can do stuff with it here.
}
So I was thinking on how to define this object, but I'm not sure how to define these events and how I should do this.
function customFileParser(){
this.parse = function(){
//Do stuff here and trigger event when it's done...
}
}
However, I'm not sure how to define these events, and how I can do this. Anyone can give me a hand?
Javscript is prototype-based OOP language, not class-based like most other popular languages. Therefore, the OOP constructs are a bit different from what you might be used to. You should ignore most websites that try to implement class-based inheritance in JS, since that's not how the language is meant to be used.
The reason people are doing it because they are used to the class-based system and are usually not even aware that are alternatives to that, so instead of trying to learn the correct way, they try to implement the way that they are more familiar with, which usually results in loads and loads of hacks or external libraries that are essentially unnecessary.
Just use the prototype.
function CustomFileParser(onParsed, onProgress) {
// constructor
this.onParsed = onParsed;
this.onProgress = onProgress;
};
CustomFileParser.prototype.parse = function(file) {
// parse the file here
var event = { foo: 'bar' };
this.onProgress(event);
// finish parsing
this.onParsed(event);
};
And you can use it like so
function parsed(event) {
alert(event);
}
function progress(event) {
alert(event);
}
var customFileParser = new CustomFileParser(parsed, progress);
var file = ''; // pseudo-file
customFileParser.parse(file);
From what it sounds to me i think you need your program to look like this
function customFileParser( onparse , progress){
this.onparse = onparse;
this.progressStatus = 0;
this.progress = progress;
this.parser = function (chunk)
}
this.parse = function(){
// Do stuff of parsing
// Determine how much data is it
// Now make a function that parses a bit of data in every run
// Keep on calling the function till the data is getting parsed
// THat function should also increase the percentage it think this can be done via setTimeout.
// After every run of the semi parser function call the progress via something like
this.parser();
if(progressStatus <100){
this.progress(this.progressStatus);
}else{
this.parsed();
}
}
}
and u can create instance of that object like
var dark = new customFileParser( function () { // this tells what to
do what parsed is complete } , function (status) { // this tells what
to do with the progress status } ) ;
using the method i suggested. you can actually define different methods for all the instances of the object you have !

AJAX (XMLHTTPRequest) time delay

I am new to AJAX and have this issue.
I am creating a photogallery page and on it I created a Javascript class which manager the whole thing. Here is a method from the class which calls XMLHTTPRequest object which was initialized successfully earlier:
this.AJAX_update = function(id) {
//initialize AJAX - this is done successfully
this.AJAX_initialize();
var url = "ScriptLibrary/gallery_update.php?img=" + id;
//this.ajax_request is an internal variable which is
//initialized in this.AJAX_initialize() and is
//XMLHTTPRequest type
this.ajax_request.open("GET", url, true);
this.ajax_request.onreadystatechange = processAJAX;
this.ajax_request.send(null);
}
I could not figure out how to call class' internal method in onreadystatechange, so I created a function outside of the class which calls a method inside the class provided that the instance of the class has been created on the page which it is. The instance of the class on the page is the variable 'gallery'. Here is the function:
function processAJAX() {
gallery.AJAX_process();
}
Here is the code of the AJAX_process() function:
this.AJAX_process = function() {
if (this.ajax_request.readyState == 4) {
if (this.ajax_request.status == 200) {
//get the response
var response = this.ajax_request.responseXML;
//Here I set the internal variables according to the value
//returned from the server
//...........
//...........
//...........
//change image on the page
var self = this;
setTimeout(function() {
self.swap_dissolve();
}, 50);
}
}
}
So, here is my question:
Initially I tried to call the internal function directly by just doing this.swap_dissolve() however it does not work. Basically the AJAX_process() method changes values of certain class' internal variables according to the response from the server, and those values are used in the swap_dissolve() to actually change the image on the page. What would happen is that swap_dissolve() would not change the image correctly because it was seeing null or not updated values of the variables AJAX_process() updated. When I added the time delay, the problem disappeared. I don't understand why that is happening. I do check that the readyState == 4, so the response from the server has been completely returned, therefore whatever values the function sets, are final and can be used right away, so why can't I use those values right away and have to wait?
Any suggestions or faults in my code to resolve this issue would be highly appreciated.
If you have any question to me, please post response to this question.
Thank you.
You want to use a 'closure' (e.g. pass a function-object to setTimeout).
Imagine this (heck, substitute it in your code to see):
// when response = 200
var someValue = "blahblah" // whatever you read in
setTimeout(function () {
alert(someValue)
}, 1000)
The alert should display "blablah" (or whatever you assigned to it). The value is available to the anonymous function object because a closure-binding has been created (the function can access the variables of the enclosing function scope(s).
Here is a reference: http://jibbering.com/faq/notes/closures/ and more of a soft intro: http://blog.morrisjohns.com/javascript_closures_for_dummies.html
Happy coding.
Edit/P.S. You can also write the AJAX handler like (it's just a closure to force the correct 'this' context -- some frameworks offer convenience functions for this):
var self = this
this.ajax_request.onreadystatechange = function () {
self.process_AJAX()
}
You can even use a double-binding, but... happy coding, again :-)

Categories