Javascript class attributes loaded async in constructor? - asynchronous

I'm struggling with JavaScript async patterns to achieve this :
I have a class (I'm using CoffeeScript) with some attributes initialized in the constructor from some async calls. Then I have some methods that require these attributes to work. Here is a simplified example of what I'm trying to do :
# Class definition
class window.MyClass
constructor: ->
#attr = ... # loaded with an ajax call or whatever
myMethod: ->
console.log #attr
# User code
c = new MyClass()
c.myMethod() # should console.log the value loaded asynchronously
So the issue will be that when myMethod() is called, the async call hasn't finished yet.
I know a few solutions, however they imply moving the method call inside a callback (or a then function with promises). I want to avoid this to be able to call this method from click handlers or something else totally unrelated.
Also note that I can't move the async call inside my method since I will probably have several methods using the attribute, and I don't want to load the attr at each call, but only in the constructor.
Any idea ?

I finally found a way to do this. Not sure if it's very clean, but it works and fits my needs.
After loading asynchronously my attr value, I dispatch an event MyClassReady.
In my constructor, I've added a first listener to MyClassReady that sets an attribute ready to true.
Then, in myMethod, I wrapped my code in a function. Then I call this function if ready is true, otherwise I bind this function to the MyClassReady event.
The result looks like this :
# Class definition
class window.MyClass
constructor: ->
# Async load of `attr`
self = this
loadAttr (val) ->
self.attr = val
window.dispatchEvent new Event 'MyClassReady'
window.addEventListener 'MyClassReady', ->
self.ready = true
myMethod: ->
self = this
callback = ->
console.log self.attr
# If the attrs are already loaded
if #ready
callback()
else
window.addEventListener 'MyClassReady', ->
callback()
# User code
c = new MyClass()
c.myMethod() # this will wait until attr is loaded
I think it would be nice to move this code to a library, however with all the self = this stuff it seems complicated.
Edit: note that custom events aren't supported by IE...

Related

How to access 'this' in a java method?

I have the following javascript method:
myFunc = function(callback) { callback.call(this, "hello", "world"); }
and I´m passing a java object that implements the 'call' method. In the java call method I get the two parameters "hello" and "world", but not 'this' (of course). Is there a way to access 'this' from java?
I´m interfacing java with d3.js and d3 has lots of callbacks in this way and 'this' is where d3 stores a selection.
Thanks
I´m not actually coding in Java but JRuby. In order to make a Java example
I´ll have to simplify my code bellow. Maybe this can help some. If not,
I´ll try to do a Java example.
# Function f1 will call the callback methods cb1 and cb2 with 'this' variable
# This is just a notation for creating javascript function. It calls
# #browser.executeJavaScriptAndReturnValue(scrpt), whith the function
# body (everything between EOT) modified to make a valid javascript script.
# f1 is a function with 2 arguments cb1, and cb2 which should be the
# callback functions
f1 = B.function(<<-EOT)
(cb1, cb2) {
cb1.call(this, "banana", "milk");
cb2.call(this, "arroz", "feijao");
}
EOT
# Proc is a closure. It receives two arguments |food1, food2|. This will
# become a java object per JRuby´s magic
proc = Proc.new { |food1, food2| puts "I hate #{food1} and #{food2}" }
# now call method f1 passing proc as the first argument and the block as
# the second argument. So cb1 = proc and cb2 = <the block bellow>. Method
# 'send' grabs the given arguments, converts them to java objects and then
# calls jxBrowser 'invoke' method with the given arguments.
f1.send(proc) { |food1, food2| puts "eu gosto de #{food1} e #{food2}" }
The result of executing this code is:
I hate banana and milk
eu gosto de arroz e feijao
As can be seen, the 'this' variable is just gone... I would like to be able to
capture the 'this' variable somehow in order to be able to use the context in the blocks. I´ve managed to make a workaround that allows capturing the 'this' variable, but it requires wrapping the block in another javascript function.
The whole idea of this code is to allow a JRuby developer to write Ruby code and get this code executed in jxBrowser without needing to use any javascript. Examples of this can already be seen by downloading mdarray-sol GEM, or going to https://github.com/rbotafogo/mdarray-sol. There you can see multiple examples of using d3.js with JRuby.
Please make sure that you follow the instruction at https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013062-calling-java-from-javascript and inject your Java object with the call() method correctly:
Java code:
browser.addScriptContextListener(new ScriptContextAdapter() {
#Override
public void onScriptContextCreated(ScriptContextEvent event) {
Browser browser = event.getBrowser();
JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty("java", new JavaObject());
}
});
...
public static class JavaObject {
public void call(JSValue window, String message) {
System.out.println(message);
}
}
JavaScript code:
window.java.call(window, 'Hello Java!');

Why this closure call doesn't end up in a recursive call?

I'm new to Groovy and I'm studying closures in the oficial docs. The 'delegate of a closure' topic gives the example bellow:
So, in the number 5, I know that delegate is set default to owner, that in the case is the enclosing closure enclosed.
So, why calling
{ -> delegate }.call()
inside the enclosed closure doesn't end up in a recursive call? Looks like a recursion to me, but if you run the code, isn't a recursion. What I'm missing here?
def enclosed = {
// delegate == owner == enclosed (variable)
{ ->
// When this closure is called return the delegate (enclosed)
delegate
}.call() // Called immediately
// above closure is same as writing
// return delegate
}
// When enclosed in called the delegate is returned immediately
// from the invocation of the inner closure, hence the result of the
// closure call is the closure (delegate) itself
assert enclosed() == enclosed
Keep in mind that whatever is suppose to happen inside enclosed closure will not happen until enclosed() is called. :) Does it depict a clear picture now?
Calling { -> delegate }.call() in the enclosed closure doesn't cause a recursive call because call() is invoked on a different closure; the one created in enclosed. To get a recursive call you can do this: { -> delegate }.call().call(). The first call() returns enclosed, and the second invokes it.

Can I override/extend Meteor methods?

Is it possible to somehow override a method in Meteor?
Or define another function such that both will get called?
In my regular code:
Meteor.methods(
foo: (parameters) ->
bar(parameters)
)
Somewhere else that gets loaded later (e.g. in tests):
Meteor.methods(
# override
foo: (parameters) ->
differentBehavior(parameters)
# I could call some super() here
)
So I would expect to either have both bar and differentBehavior executed or only differentBehavior and some possibility to call super().
Does this exist?
To override a method, on server side you can do:
Meteor.methods({
'method_name': function () {
//old method definition
}
});
Meteor.default_server.method_handlers['method_name'] = function (args) {
//put your new code here
};
The Meteor.default_server.method_handlers['method_name'] has to be included after the method definition.
To override a method (also know as a stub), on client side you can do:
Meteor.connection._methodHandlers['method_name'] = function (args) {
//put your new code here
};
The Meteor.connection._methodHandlers['method_name'] has to be included after the method definition.
There are lots of ways you can do what you are intending to do.
For instance, the simplest way to overwrite any function would be to do something like:
Meteor.publish = function() { /* My custom function code */ };
We just over-wrote the Meteor.publish with our own instance.
However, if you want to wrapper a function like a proxy (I believe this is called a "proxy pattern":
var oldPublish = Meteor.publish();
Meteor.publish = function() {
oldPublish(arguments); // Call old JS with arguments passed in
}
ES6 also added a Proxy object that allows you to do some similar things (read about it here).
Also there are lots of AOP libraries (CujoJS, jQuery-AOP, and node-aop to name a few) for JavaScript that allow you to do before, after, around pointcuts on functions/objects. You could even roll-your-own if you wanted too.

What is a proper way of using reflection in AX?

Sometimes, when I need to do more complicated stuff than change one value in datasource, I would like some method on caller. For example I have a form A with overview. Form A has method setName() (I define). I open a related detail (form B). I change something and I want to call setName on caller.
Nowdays I am doing it in following way
element.args().caller().setName();
but I am looking for more idiomatic way. So what is proper way of calling method on caller in AX 2012 R3?
It sounds like you need to change your development methodology if you referencing that many caller-form methods. You would mostly do that for calling doRefresh or calling updateDesign, which are both typically created methods on forms. Beyond updating the design and refeshing, you should use a class form handler.
If you must do a caller-callback, you can validate by doing:
if (formHasMethod(element.args().caller(), identifierstr(updateDesign)))
{
element.args().caller().updateDesign();
}
You can pass your class as the caller. Here is a simple sample set of code:
\Forms\Form1\Designs\Design\[Group:Group]\Button:Button\Methods\clicked:
void clicked()
{
FormRun formRun;
Args args = new Args(formstr(Form2));
TestClass testLocal = new TestClass();
testLocal.parmTestVar('ZZZ');
args.caller(testLocal);
formRun = classfactory.formRunClass(args);
formRun.init();
formRun.run();
formRun.wait(true);
}
\Forms\Form2\Methods\init:
public void init()
{
TestClass testClass;
super();
testClass = element.args().caller() as testClass;
info(strFmt("%1", testClass.parmTestVar()));
}
Look at \Forms\SalesTable and \Classes\SalesTableForm or \Classes\SysCompare\startCompareOfContextProvider and the init method
identifierStr is not depreciated. It's a normal intrinsic function, but you will get a best practice warning if you use the identifierStr function. This is because no existence checking is carried out for identifierStr. Try to use a more specific intrinsic function if one is available. See http://msdn.microsoft.com/en-us/library/aa626893.aspx
You could take a look at Calling methods on a caller form, but identifierStr is deprecated in AX 2012. As far as I know there is no way to check for form methods at compile time.
But I would suggest avoiding methods on forms. Place them in a form handler class instead, you can then use the methodStr function to check for a method.

Multiple asynchronous calls to populate an object

I'm developing a Flex application and am having some trouble working with asynchronous calls. This is what I would like to be able do:
[Bindable] var fooTypes : ArrayCollection();
for each (var fooType : FooType in getFooTypes()) {
fooType.fooCount = getFooCountForType(fooType);
itemTypes.addItem(fooType);
}
The issue I'm running into is that both getFooTypes and getFooCountForType are asynchronous calls to a web service. I understand how to populate fooTypes by setting a Responder and using ResultEvent, but how can I call another service using the result? Are there any suggestions/patterns/frameworks for handling this?
If possible, I Strongly recommed re-working your remote services to return all the data you need in one swoop.
But, if you do not feel that is possible or practical for whatever reason, I would recommend doing some type of remote call chaining.
Add all the "remote calls" you want to make in array. Call the first one. In the result handler process the results and then pop the next one and call it.
I'm a bit unclear from your code sample when you are calling the remote call, but I assume it part of the getFooCountForType method. Conceptually I would do something like this. Define the array of calls to make:
public var callsToMake : Array = new Array();
cache the currently in process fooType:
public var fooType : FooType;
Do your loop and store the results:
for each (var fooType : FooType in getFooTypes()) {
callsToMake.push(fooType);
// based on your code sample I'm unclear if adding the fooTypes to itemTypes is best done here or in the result handler
itemTypes.addItem(fooType);
}
Then call the remote handler and save the foo you're processing:
fooType = callsToMake.pop();
getFooCountForType(fooTypeToProcess);
In the result handler do something like this:
// process results, possibly by setting
fooType.fooCount = results.someResult;
and call the remote method again:
fooType = callsToMake.pop();
getFooCountForType(fooTypeToProcess);

Resources