Ember.js Observer on computed property, not working. Example from guides - ember.js

I am learning Ember.js and going through some of the guides. I was reading about observers here:
http://emberjs.com/guides/object-model/observers/
I wanted to play around with the example so I copied and pasted it into my js file. After adding an alert statement to the observer callback, I was surprised to find it was not invoked.
http://jsbin.com/UWEseSo/2/edit?js,output
I was able to find that if you add:
person.get('fullName');
Before the call to set the firstName, the observer callback will be invoked. If I set the first name again immediately after the callback would again not be invoked.
Can anyone explain what is going on here?
Thank you.
EDIT-------
I've traced through the code a little more and I now I have an idea on why this behavior may be like this. Although the example seems like there is a bug it may just be an optimization. I observed earlier that if I called "get" the observer would work. If I did not call "get" the observer would not work. I believe Ember.js may just being smart about this and intentionally not bothering to invoke the observer if no "get" was called. They may be doing this because if there was no "get" there is no reason to invoke the observer because the application can not possibly be showing out of date information.
Once "get" is called an internal flag is set to ensure the observer will be invoked on the next "set".

It looks like you got the explanation right for this behaviour all by yourself, and to confirm your assumptions there is indeed a change that was introduced in rc8 for performance reason mainly.
You can read here the full article on that, under UNCONSUMED COMPUTED PROPERTIES DO NOT TRIGGER OBSERVERS
This means basically that if you need to observe a computed property but aren't currently retrieving it, just get it in your init method.
Hope it helps.

Related

Ember js: Setting a property only once (in an observer) throws Deprecation Warning You modified X twice in a single render

I am running into quite some peculiar behavior. The thing is I understand the deprecation warning, however, it should not be happening as an 'observes', IMHO, does not use a getter, so, setting a property should not cause the deprecation.
I am using Ember 2.2.0 and Ember-Cli 1.13.8. Everything is structured in Components and, if need be, Services (global singletons). Here's a simplified version of my code. I should maybe make a JSFiddle and try to reproduce it, but I figured someone might spot the error directly.
Parent component template:
{{my-component model=service.currentModel changed=changed}}
my-component.js:
watchChanged: function() {
this.set('model', this.get('some_internal_value')); //this throws deprecation, even though it should not
this.get('parentView').send('resetChanged'); // reset changed in the parent
}.observes('changed', 'some_internal_value')
I went with the debugger and watchChanged is called EXACTLY ONCE, in spite of this fact, the deprecation warning is thrown. The code works perfectly, save for the deprecation warning. Any ideas?
My workaround is to do the set as a task in the 'afterRender' queue, but this isn't a solution for the issues that I am experiencing.
What is the "ember-way" in this case? Is it a bug or a lack of understanding on my side?
Edit: cross-posted it here.
Edit x1: There are no didInsertElement/willInsertElement hooks implemented in the parent, nor in the child. I assume that the service querying is somehow causing it... but I do not have enough experience with services to say for sure.
I can't see enough of the {{my-component}} code to say for sure, but my guess is that either changed or some_internal_value, or one of their dependencies, are being updated as part of a rendering lifecycle hook. Commonly this is willRender or didInsertElement. Check for those in your component, try commenting them out temporarily to test.
Sometimes an afterRender is necessary, but you should definitely avoid it as much as possible.

In QtWebkit, how does a webpage's QNetworkAccessManager::createRequest() get invoked?

I'm building a Browser application using the QtWebkit and QtNetwork modules.
Let's say that it's a requirement that each webpage only be able to access resources from only a specific folder, set aside specifically for it. In this scenario, each webpage would have some kind of ID to identify it which could be used to verify that it's accessing the correct folder.
The problem is that it's not clear how exactly the createRequest() method gets invoked. If it's a signal that's emitted or something then I would be able to intercept it and add a few parameters indicating webpage ID.
As such now the only option open to me is to create a separate QNetworkAccessManager for each QWebPage and overload the createRequest() function whereas I would really like to be able to share the QNetworkAccessManager across QWebPages.
Alternate solutions would be appreciated but generally I'm also really confused about how the createRequest() method is reached.
Reference :
QNetworkAccessManager::createRequest
It's not a big deal to have a separate access manager for each web page. You don't have any measurements to show it to be a problem, so in a true Don Quixote fashion, you're fighting windmills and imaginary enemies :)
The createRequest virtual method is called by the various non-virtual request methods: get, post and put. It's a good example of the non virtual interface (NVI) pattern.

BHO: getting a notification when onload finishes executing

I'm writing a BHO that should make a slight modification to a specific page. I'd be using DISPID_DOCUMENTCOMPLETE, but the problem is that the page loads more contents using AJAX on it's onload function.
I think the perfect solution for me would be to run my code after onload has returned. Is there any way to get notified when this happens?
Edit: Actually, its not onload, it's jQuery's ready. I'm afraid there's no clean way to achieve what I want. I guess I'll have to implement a timer and check the page periodically, although I hoped to avoid that.
You could try to use DISPID_HTMLDOCUMENTEVENTS2_ONREADYSTATECHANGE (you must advise for DIID_HTMLDocumentEvents2) and then use get_readyState from IHTMLDocument2.
You are lucky that your page is a specific one, you may see a specific sequence of events you can rely on. The general case indeed involves periodic poll (imho)

Calling a function after another function is called

I'm programming a controller for use with Ableton Live 8 using the Python-based API. In my code I use a method provided in the API to watch for changes in a property's value, and call a function whenever the value changes. My goal is to change the color of the clip when the value change is noticed.
I have my code completed, and it compiles without error. From Ableton's log:
742234 ms. RemoteScriptError: RuntimeError
742234 ms. RemoteScriptError: :
742234 ms. RemoteScriptError: Changes cannot be triggered by notifications
742234 ms. RemoteScriptError:
It appears this is the result of using the built-in notification system to make a change to the live set during notification. Triggering the actual change AFTER the listening function has finished executing should work. Is this possible using Python?
Edit for clarification:
currently we have
value change noticed, function called
function attempts to change the clips color (results in error)
we need
listener notices value change, function called
function finds the new color value
function execution ends
another function is called outside the listener's scope, and changes the clips color
I did a lot in M4L and know this error by heart :)
I'm afraid you can't do anything about that - to my noob eyes it looks like a built-in security mechanism so you can't loop (Something changed? Change it! Something changed...).
In M4L i used Javascript Tasks to separate the steps (Tasks forget nearly everything),
something like
Observer -> Something changed
Create a Task that reacts
task.execute() or task.schedule(time)
Maybe the python threading module can achieve something similar?
BTW, if you happen to understand anything about the _Framework-Tasks, let me know.
I was having the same issue trying to delete a track from a clip stop listener, then I found this thread and followed #user2323980 suggestion.
There seems to be a "_tasks" object on every Framework class (I found it throught log_message inside ClipSlotComponent and ControlSurface) that handles concurrency between tasks. And it's really simple to use it:
self._tasks.add(Task.run(func, args))
I found some uses of it on Push and MK2 scripts, those are good references.

Recording state changes in boost::statechart

For Unit Testing, I'm trying to record all the state transactions after I kick off a state machine event.
E.g., if I post_event A to the fifo_scheduler of an async_state_machine, the state machine will go through states B, C, then back to D.
Without being able to record all the event states, I can only check that it went to State D after it was done when doing a unit test :-(
The only thing I can think of is to modify all the react methods or constructors of all the states I create (derived off simple_state) so they do the recording. This seems a bit hackish when I really want to hook into the async_state_machine just before it calls a state's react() method...
This seems a bit hackish when I really want to hook into the async_state_machine just before it calls a state's react() method...
Why don't you? Create a new class that extends async_state_machine and add your desired hooks into it. If access is a problem (It probably will be), do the ever spectacular #define private public (or protected hack before including statechart.
I've done something similar to add local variables to the history of a state and add a new kind of state-ctor so I have for-real full history.
Added a different hack. Each State is created before it's used by the boost state machine (then destroyed after it goes to the next state...seems so inefficient), so each state was derived from another class that has a callback in it's constructor.
Still seems kinda hackish...wish boost++ had a cleaner way to do this :-P