Strange AUI behaviour - liferay-aui

Up until now i assumed a call to AUI would be processed synchronously within the embedding JavaScript. Now I noticed the following behaviour:
Liferay.on('allPortletsReady',
function() {
AUI().use('node', function(A) {
// (1) --> set some global var here
});
// (2) --> use global var here
}
);
I expected the execution order
(1)
(2)
I got
(2)
(2)
(2)
(1)
(1)
(1)
I could live with the triple execution but I can't explain the reverse order.
The problem was easily solved by moving (2) inside the AUI sandbox, but I still wonder...

First of all, .use() is called asynchronously. When calling AUI().use('node', function(A) {...});, the node-module has to be loaded and attached before the the function inside (function(A) {...}) is called.
So what is happening is that while the node-module is being loaded, the code lines after use() are being called, and when the module has been successfully loaded and attached, the function (function(A) {...}) is called.
See the documentation on .use() here: http://yuilibrary.com/yui/docs/yui/#understanding-yuiuse
(AUI is an extension of YUI)
This might also be helpful: Getting started with YUI3 and AlloyUI

Related

AngularJS $window.open throws "Cannot read property 'arguments' of null"

I'm creating a simple web page where i display a button which execute this code
$window.open(link, "_self");
The link variable is a simple telegram link for a channel, but this is not the problem, the problem, as the question say itself, is about arguments variable in $window.open.
This in my opinion is strange because when i logged in the console $window.open function, i received this output:
function pbWindowOpen() {
lastBlockCaller = {
caller: arguments.callee.caller,
args: arguments.callee.caller.arguments
};
try {
return newWindowOpenFn.apply(this, argument…
At this point, should not i see an argument variable inside this function? How could i solve this problem?
Passing some arguments could resolve my problem? If yes, there's an answer about why i'm having arguments null?
I've also tried with window.open but nothing changes, always the same problem
That shouldn't happen if you are running your code in a browser (in other env you may have some initialized variable window representing something else), $window is a wrapper in top of var currWindow = $window.self || $window.window and then do a perform of callong open(...) function. Hence, you neither using the native javascript code badly in a angular context, and again that would be easily mock-ableif we mock $window and create a property call self or window inside it. So it will work in the application, and will also be testable.

ng-repeat too many iterations

I am using angular-meteor and would like to perform a function on each object. I tried running this function within an ng-repeat in the view, but I am getting massive amounts of function calls and can't figure out why. I tried to make it as simple as possible to demonstrate what is going on.
constructor($scope, $reactive) {
'ngInject';
$reactive(this).attach($scope);
this.loaderCount = 0;
this.helpers({
loaders() {
return Loaders.find( {isloader:true}, {sort: { name : 1 } })
}
});
That gives me 26 Loaders. My function just adds 1 to the count every time the function is called:
displayLoaderCount()
{
return ++this.loaderCount;
}
Now in my view, I am looping through each loader, and calling the function. This should in my mind give me 26, but instead I am getting 3836.
<tr ng-repeat="loader in loaderExhaustion.loaders">
<td>{{loaderExhaustion.displayLoaderCount()}}</td>
Can anyone help explain this to me? Ideally I would like to loop over the contents in my module but as the collection is async, when the loop starts the length of the collection is 0, hence why I made the call in the view.
THANKS!
Every time angular enters a change detection cycle, it evaluates loaderExhaustion.displayLoaderCount(), to know if the result of this expression has changed, and update the DOM if it has. This function changes the state of the controller (since it increments this.loaderCount), which thus triggers an additional change detection loop, which reevaluates the expression, which changes the state of the controller, etc. etc.
You MAY NOT change the state in an expression like that. For a given state, angular should be able to call this function twice, and get the same result twice. Expressions like these must NOT have side effects.
I can't understand what you want to achieve by doing so, so it's hard to tell what you should do instead.

check if callback is registered with angular's deferred object [duplicate]

I want to return a $q instance so that if clients don't call 'then' with a reject handler, then a default one runs.
E.g. assume the default is to alert(1)
Then mypromise.then(function(result){...}) will alert 1 but mypromise.then(null, function(reason){alert(2)}) will alert 2
Let's assume there was a way to do that.
So we have a magical machine that can always find out if .then is called with a function second argument for a specific promise or not.
So what?
So you can detect if someone did:
myPromise.then(..., function(){ F(); });
At any point from anywhere at any time. And have G() as a default action.
And...?
You could take a whole program containing lots of code P (1) and convert that code to:
var myPromise = $q.reject();
P; // inline the program's code
myPromise.then(null, function(){}); // attach a handler
Great, so I can do that, so?
Well, now our magical machine can take an arbitrary program P and detect if myPromise had a rejection handler added to it. Now this happens if and only if P does not contain an infinite loop (i.e. it halts). Thus, our method of detecting if a catch handler is ever added is reduced to the halting problem. Which is impossible. (2)
So generally - it is impossible to detect if a .catch handler is ever attached to a promise.
Stop with the mumbu-jumbo, I want a solution!
Good response! Like many problems this one is theoretically impossible but in practice easy enough to solve for practical cases. The key here is a heuristic:
If an error handler is not attached within a microtask (digest in Angular) - no error handlers are ever attached and we can fire the default handler instead.
That is roughly: You never .then(null, function(){}) asynchronously. Promises are resolved asynchronously but the handlers are usually attached synchronously so this works nicely.
// keeping as library agnostic as possible.
var p = myPromiseSource(); // get a promise from source
var then = p.then; // in 1.3+ you can get the constructor and use prototype instead
var t = setTimeout(function(){ // in angular use $timeout, not a microtask but ok
defaultActionCall(p);// perform the default action!
});
// .catch delegates to `.then` in virtually every library I read so just `then`
p.then = function then(onFulfilled, onRejected){
// delegate, I omitted progression since no one should use it ever anyway.
if(typeof onRejected === "function"){ // remove default action
clearTimeout(t); // `timeout.cancel(t)` in Angular
}
return then.call(this, onFulfilled, onRejected);
};
Is that all?
Well, I just want to add that cases where this extreme approach is needed are rare. When discussing adding rejection tracking to io - several people suggested that if a promise is rejected without a catch then the whole app should likely terminate. So take extra care :)
(1) assume P does not contain a variable myPromise, if it does rename myPromise to something P does not contain.
(2) Of course - one can say that it is enough to read the code of P and not run it in order to detect myPromise gets a rejection handler. Formally we say that we change every return in P and other forms of termination to a return myPromise.then(null, function(){}) instead of simply putting it in the end. this way the "conditionality" is captured.

Need explanation on a angular direcive load

I just want to understand why in the following jsFiddle 'here is a lo' is printed three times.
http://jsfiddle.net/wg385a1h/5/
$scope.getLog = function () {
console.log('here is a log');
}
Can someone explain me why ? What should I change to have only one log "here is a log" (that's what I would like this fiddle do). Thanks a lot.
Angular uses digest cycles/iterations to determine when state has changed and needs to update the UI. If it finds any change on one of it's cycles, it keeps rerunning cycles until the data stabilizes itself. If it's done 10 cycles and the data is still changing, you'll see a rather know message: "angularjs 10 iterations reached. aborting".
Therefor, The fact that you are seeing the message displayed 3 times is because you have a simple interface. In fact, you can get up to many more such messages in the log, due to the fact that your directive uses {{getLog()}}. Angular keeps evaluating the expression to see if it changed.
To avoid such problems, under normal circumstances, you should store the value returned by the function you want called only once in the $scope object inside the controller and use that variable (not the function call) in the UI.
So in the controller you'd have $scope.log = getLog() [assuming it returns something, and not just writing to the console] and in the directive use the template {{log}}. This way, you'll get the value only once, per controller instance.
Hope I was clear enough.

ng-table , getData called more than once, why?

For some reason when getData uses angular resource to bring the data it is being called twice, causing the resource to do it REST request twice too <--- bad...
Any idea why and how to solve it?
Here a working testcase/plunker example that recreates this scenario (look at the browser console - "getData being called...." displayed twice ) b.t.w as you can see I'm not really using the resource to bring real data, just to demonstrate the scenario, In my real app I do use the resource to bring real data and its being called twice just like in this example,
Thanks ahead
After looking into the src of the ng-table I noticed the following
$scope.$watch('params.$params', function(params) {
$scope.params.settings().$scope = $scope;
$scope.params.reload();
}, true);
Which means that the tables calls it 'getData' on count/filter/group/groupBy/page/sorting
which explains the behavior I was seeing.
When you call params.count(...) you ask ng-table to refresh data as you change page size. That's why you have two get-data calls.
If you don't want to have paging, then remove calls params.count and params.total.
If you need paging, then set page size and do not change it in getData.
This happened to me with a weird reason. getData get called twice on init (first load) only. changing page or sorting didn't call getData twice. The reason was that at init the ng-table directive was hidden in the template file.
Thank #Alexander Vasilyev. I understood my problem as you said. I want to explain a litte more here. In fact, the object "params" is the object configuration the table ng-table, then if "params" changed (ex: count or a property of the object), ng-table will invoke function getData() to refresh table.
In my case, I want to get information in the object "params" and change it but I dont want to refresh ng-table. I did it by cloning object "params" et work his object copied. Clone the object in JS with jQuery :
var resultParams = jQuery.extend(true, {}, params.$params);
And then, I will work on the object resultParams instead of "params" original.

Resources