Enumerate events/eventListeners for a WinJS object - winjs

I'm using pure WinJS for a project (No jQuery) and have run into a requirement that has me stumped.
Let's say I have a DOM element called 'bob' (although this might not necessarily be a DOM element). To attach an event listener, I would do this:
bob.addEventListener('click', function ()
{
// Some code goes here
});
There is nothing stopping me from adding lots of event listeners to 'bob', even for the same event names (which is fine as they are just queued) - herein lies the rub!
I need to be able to enumerate the events/listeners that are attached to a given object so I can selectively replace or tweak some of them at runtime.
Any thoughts on how to acheive this?

It's not possible to enumerate events added using addEventListener. The way you're adding the event is not recommended (at least by me :). You're using addEventListener but then using an anonymous method. If you do that then you'll never be able to remove that event because you don't have a handle to it. I would recommend creating your function and then assigning the named function (myelement.addEventListener("event", myfunction)). Each time you add an event to your element, just add it to a collection (an array hanging off the element itself) and then you'll have your list of events.

It turns out that you can, in some circumstances, enumerate attached event listeners.
If you are using the 'Events' Mixin on an object, then once you have called one of the mixed-in methods (addEventListener, removeEventListener or dispatchEvent), your target object will gain a property called _listeners (assuming it doesn't already exist).
For a practical example, here's a function that counts the number of attached event listeners for an object that uses this mixin:
/*
* Counts the number of attached listeners
*/
countListeners: function()
{
var count = 0;
if (this._listeners)
{
var key;
for (key in this._listeners)
{
if (this._listeners.hasOwnProperty(key))
{
count++;
}
}
}
return count;
}
Hope this helps someone!
G

Related

LitElement and .bind(this)

I'm finding a little confusing sometimes you need to bind the context to a function call and sometimes not. When exactly can you avoid it and when you not?
What's the difference between those lines?
<a #click="${this.handler.bind(this)}">link</a>
<a #click="${this.handler()}">link</a>
<a #click="${this.handler}">link</a>
<a #click="${()=>this.handler()}">link</a>
Also sometimes in the constructor() you need
this.handler = this.handler.bind(this)
to make the function call works, sometimes you not. What's the differences between all those cases?
In the first 4 lines I am guessing you usually wrap them in between ${ and }.
With this mention these 3 lines:
<a #click="${this.handler.bind(this)}">link</a>
<a #click="${this.handler}">link</a>
<a #click="${()=>this.handler()}">link</a>
would be pretty similar in the effect. When you attach an event handler you need to pass a reference to a function/method to call, while the second line:
<a #click="${this.handler()}">link</a>
will most likely just be wrong. That's because you will be calling this.handler() as soon as the rendering is done. The only way it might make some sense it would be if the handler method returns a function.
Going back to the first 3 lines: they will indeed have very similar effect, as in all of them you are passing references to a local method render, but:
the first one doesn't need binding as the method will anyway be
called in this context (but I guess it doesn't hurt either)
the third one adds the definition of an anonymous function as an
event handler, which when called it will invoke this.handler
So the second one is basically the simplest and easiest to read.
When it comes to the need to call bind in some of the cases: that's needed when your method is called from another context. Let's say you pass it as a callback parameter to a method running in another class. When you method will be called there, it will have by default the context of that other object. So you will need to use .bind(this) to make sure that when the method is called in your element's context.
Your method does work, but it's running from another this. So maybe that's why some of the times you don't notice the need to .bind(this). If the method just shows a message, calls some other external service, or anything else that is not part of your object's definition (that doesn't use this.something), it will work without using bind.
UPDATE: in fact I think an event handler will always run in the context of the element that originated that event. I am guessing that lit just does that .bind(this) when we use that #click= syntax, as it would make a lot of sense.
Note that binding directly in templates is generally not a good idea. It can result in performance issues and components re-rendering when they shouldn't.
https://github.com/43081j/eslint-plugin-lit/blob/master/docs/rules/no-template-bind.md
As to why you sometimes need to bind consider this:
#customElement('main-page')
export class MainPage extends LitElement {
#property()
public name = "bob";
render() {
return html`<button #click=${this.clicked}>Click Me!</button>`;
}
clicked() {
console.log("clicked " + this.name);
console.log("this in clicked: " + this)
setTimeout(this.sayHi, 1000);
}
sayHi() {
console.log("this in sayHi: " + this)
alert(`Hello, ${this.name}!`);
}
}
If we click on the button, we get the name logged properly:
But the name isn't shown in the alert:
If we look at this in both functions we get different results:
One is an HTMLElement and the other one is a Window. What this refers to is different once we pass sayHi to setTimeout.
Bind will fix this by making sure that this refers to the right object.
While we could do setTimeout(this.sayHi.bind(this), 1000); and it would fix our issue but it's not very clean and it's error prone. We could bind it in the constructor, but this also isn't much better.
The cleanest way to do it is to directly bind this by using an arrow function instead:
sayHi = () => {
[...]
This notation binds this to the object itself. We then do not need to bind it explicitly ourselves.
Once we do that, both this refer to the right object:

Node emitter : how to properly design event listeners

I'm learning node:
Looking inside the EventEmitter, by default it executes callbacks by passing the emitter as this to the event listener, such that within your event listener function, this refers to the EventEmitter object.
I'm somewhat confused by this sentiment, how can an object register itself as a listener and keep a reference to its own properties?
Consider this problemo:
Meeting.prototype.recordStatement = function(name, statement) {
this.minutes.push(name + " said " + statement);
};
It's pretty standard to use a pattern like this to create instance methods for custom objects, but this won't fly as a listener for an EventEmitter: If I attach the recordStatement instance method of a meeting to, say, statements events emitted by, say, a person/emitter, I lose access to the meeting instance properties within the scope of the recordStatement listener, so with respect to the above example, on statement event from the person, this.minutes is undefined.
I suppose I can use an intermediate object here, which would hold a reference to the meeting instance, but, seems like a lot of wiring.
How should I design for this? Thanks!
Wrap the function call in a closure:
var self = this;
emitter.on('statement', function(name, statement) {
self.recordStatement(name, statement);
});
Or use .bind() (can be slower than using a closure):
emitter.on('statement', this.recordStatement.bind(this));

Portable Class Library and ObservableCollection, updating UI Thread

I'm not very experienced with this topic so forgive me if this isn't very clear.
I've created a Portable Class Library that has an ObservableCollection of Sections, and each secion has an ObservableCollection of Items.
Both of these collections are bound to the UI of separate Win8 and WP8 apps.
I'm trying to figure out the correct way to populate these collections correctly so that the UI gets updated from the PCL class.
If the class was inside the win8 project I know I could do something like Dispatcher.BeginInvoke, but this doesn't translate to the PCL, nor would I be able to reuse that in the WP8 project.
In this thread (Portable class library equivalent of Dispatcher.Invoke or Dispatcher.RunAsync) I discovered the SynchroniationContext class.
I passed in a reference to the main app's SynchroniationContext, and when I populate the sections I can do so because it's only the one object being updated:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
UpdateSections(sections);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post(UpdateSections, sections);
}
However, when I try to do the same thing with articles, I have to have a reference to both the section AND the article, but the Post method only allows me to pass in a single object.
I attempted to use a lambda expression:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
section.Items.Add(item);
}, null);
}
but I'm guessing this is not correct as I'm getting an error about being "marshalled for a different thread".
So where am I going wrong here? how can I update both collections correctly from the PCL so that both apps can also update their UI?
many thanks!
Hard to say without seeing the rest of the code but I doubt is has anything to do with Portable Class Libraries. It would be good to see the details about the exception (type, message and stack trace).
The way you call Post() with more than argument looks correct. What happens if you remove the if check and simply always go through SynchronizationContext.Post()?
BTW: I don't explicitly pass in the SynchronizationContext. I assume that the ViewModel is created on the UI Thread. This allows me to capture it like this:
public class MyViewModel
{
private SynchronizationContext _context = SynchronizationContext.Current;
}
I would recommend that at least in your ViewModels, all publicly observable state changes (ie property change notifications and modifications to ObservableCollections) happen on the UI thread. I’d recommend doing the same thing with your model state changes, but it might make sense to let them make changes on different threads and marshal those changes to the UI thread in your ViewModels.
To do this, of course, you need to be able to switch to the UI thread in portable code. If SynchronizationContext isn’t working for you, then just create your own abstraction for the dispatcher (ie IRunOnUIThread).
The reason you were getting the "marshalled on a different thread" error is that you weren't passing the item to add to the list as the "state" object on the Post(action, state) method.
Your code should look like this:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
var item = (YourItemnType) e;
section.Items.Add(item);
}, item);
}
If you make that change, your code will work fine from a PCL.

QML: running functions in parallel threads

In my code I'm creating 16x16 buttons in cycle and this take few seconds.
onCreateField:
{
for(var i=0;i<fieldWidth;i++)
{
for(var j=0;j<fieldHeight;j++)
{
createButton(i, j);
}
}
}
function createButton(x, y)
{
__buttonX = x;
__buttonY = y;
__component = Qt.createComponent("GameButton.qml");
if(__component != null)
continueButtonCreation();
else
__component.ready.connect(continueButtonCreation);
}
function continueButtonCreation()
{
var button = __component.createObject(field, {"row": __buttonY, "column": __buttonX});
if (button == null) {
// Error Handling
console.log("Error creating object");
return;
}
updateValveState.connect(button.stateUpdated);
button.buttonClicked.connect(buttonClicked);
field.clearField.connect(button.release);
}
While function that creating buttons runs, app freezes. I want to show loading animation while this function runs. So, how to run this function in parallel thread to avoid freezing?
To do work in threads you have two possible approaches :
Read about the WorkerScript element. It allows you to perform certain operation by running the javascript functions as threads.
Note: As given in the documentation, there is a restriction though :
Since the WorkerScript.onMessage() function is run in a separate
thread, the JavaScript file is evaluated in a context separate from
the main QML engine. This means that unlike an ordinary JavaScript
file that is imported into QML, the script.js in the above example
cannot access the properties, methods or other attributes of the QML
item, nor can it access any context properties set on the QML object
through QDeclarativeContext. Additionally, there are restrictions on
the types of values that can be passed to and from the worker script.
See the sendMessage() documentation for details.
Just see, if for your particular use case it suits the requirement.
2
. Implement the functionality which are heavy as C++ threads. Whenever required, generate a signal to start this thread on the C++ side. When done, pass back the data from C++ to Qml , if required.
As you may or may not have determined in other posts you cannot load QML objects in javascript in parallel. Depending on your circumstances you should probably be using a GridView with a Delegate that renders a button. This allows the underlying code to efficently render the buttons instead of sequentially creating them in javascript.
Other options to not block the UI might be
use incubateObject instead of createObject
don't create all Buttons within a single (16ms) frame: use a Timer to spread the creation of the Buttons over multiple frames

How can I implement callback functions in a QObject-derived class which are called from non-Qt multi-threaded libraries?

(Pseudo-)Code
Here is a non-compilable code-sketch of the concepts I am having trouble with:
struct Data {};
struct A {};
struct B {};
struct C {};
/* and many many more...*/
template<typename T>
class Listener {
public:
Listener(MyObject* worker):worker(worker)
{ /* do some magic to register with RTI DDS */ };
public:
// This function is used ass a callback from RTI DDS, i.e. it will be
// called from other threads when new Data is available
void callBackFunction(Data d)
{
T t = extractFromData(d);
// Option 1: direct function call
// works somewhat, but shows "QObject::startTimer: timers cannot be started
// from another thread" at the console...
worker->doSomeWorkWithData(t); //
// Option 2: Use invokeMethod:
// seems to fail, as the macro expands including '"T"' and that type isn't
// registered with the QMetaType system...
// QMetaObject::invokeMethod(worker,"doSomeGraphicsWork",Qt::AutoConnection,
// Q_ARG(T, t)
// );
// Option 3: use signals slots
// fails as I can't make Listener, a template class, a QObject...
// emit workNeedsToBeDone(t);
}
private:
MyObject* worker;
T extractFromData(Data d){ return T(d);};
};
class MyObject : public QObject {
Q_OBJECT
public Q_SLOTS:
void doSomeWorkWithData(A a); // This one affects some QGraphicsItems.
void doSomeWorkWithData(B b){};
void doSomeWorkWithData(C c){};
public:
MyObject():QObject(nullptr){};
void init()
{
// listeners are not created in the constructor, but they should have the
// same thread affinity as the MyObject instance that creates them...
// (which in this example--and in my actual code--would be the main GUI
// thread...)
new Listener<A>(this);
new Listener<B>(this);
new Listener<C>(this);
};
};
main()
{
QApplication app;
/* plenty of stuff to set up RTI DDS and other things... */
auto myObject = new MyObject();
/* stuff resulting in the need to separate "construction" and "initialization" */
myObject.init();
return app.exec();
};
Some more details from the actual code:
The Listener in the example is a RTI DataReaderListener, the callback
function is onDataAvailable()
What I would like to accomplish
I am trying to write a little distributed program that uses RTI's Connext DDS for communication and Qt5 for the GUI stuff--however, I don't believe those details do matter much as the problem, as far as I understood it, boils down to the following:
I have a QObject-derived object myObject whose thread affinity might or might not be with the main GUI thread (but for simplicity, let's assume that is the case.)
I want that object to react to event's which happen in another, non-Qt 3rd-party library (in my example code above represented by the functions doSomeWorkWithData().
What I understand so far as to why this is problematic
Disclaimer: As usual, there is always more than one new thing one learns when starting a new project. For me, the new things here are/were RTI's Connext and (apparently) my first time where I myself have to deal with threads.
From reading about threading in Qt (1,2,3,4, and 5 ) it seems to me that
QObjects in general are not thread safe, i.e. I have to be a little careful about things
Using the right way of "communicating" with QObjects should allow me to avoid having to deal with mutexes etc myself, i.e. somebody else (Qt?) can take care of serializing access for me.
As a result from that, I can't simply have (random) calls to MyClass::doSomeWorkWithData() but I need to serialize that. One, presumably easy, way to do so is to post an event to the event queue myObject lives in which--when time is available--will trigger the execution of the desired method, MyClass::doSomeWorkWithData() in my case.
What I have tried to make things work
I have confirmed that myObject, when instantiated similarly as in the sample code above, is affiliated with the main GUI thread, i.e. myObject.thread() == QApplication::instance()->thread().
With that given, I have tried three options so far:
Option 1: Directly calling the function
This approach is based upon the fact that
- myObject lives in the GUI thread
- All the created listeners are also affiliated with the GUI thread as they are
created by `myObject' and inherit its thread that way
This actually results in the fact that doSomeWorkWithData() is executed. However,
some of those functions manipulate QGraphicsItems and whenever that is the case I get
error messages reading: "QObject::startTimer: timers cannot be started from another
thread".
Option 2: Posting an event via QMetaObject::invokeMethod()
Trying to circumvent this problem by properly posting an event for myObject, I
tried to mark MyObject::doSomeWorkWithData() with Q_INVOKABLE, but I failed at invoking the
method as I need to pass arguments with Q_ARG. I properly registered and declared my custom types
represented by struct A, etc. in the example), but I failed at the fact the
Q_ARG expanded to include a literal of the type of the argument, which in the
templated case didn't work ("T" isn't a registered or declared type).
Trying to use conventional signals and slots
This approach essentially directly failed at the fact that the QMeta system doesn't
work with templates, i.e. it seems to me that there simply can't be any templated QObjects.
What I would like help with
After spending about a week on attempting to fix this, reading up on threads (and uncovering some other issues in my code), I would really like to get this done right.
As such, I would really appreciate if :
somebody could show me a generic way of how a QObject's member function can be called via a callback function from another 3rd-party library (or anything else for that matter) from a different, non QThread-controlled, thread.
somebody could explain to me why Option 1 works if I simply don't create a GUI, i.e. do all the same work, just without a QGraphcisScene visualizing it (and the project's app being a QCoreApplication instead of a QApplication and all the graphics related work #defineed out).
Any, and I mean absolutely any, straw I could grasp on is truly appreciated.
Update
Based on the accepted answer I altered my code to deal with callbacks from other threads: I introduced a thread check at the beginning of my void doSomeWorkWithData() functions:
void doSomeWorkWithData(A a)
{
if( QThread::currentThread() != this->thread() )
{
QMetaObject::invokeMethod( this,"doSomeWorkWithData"
,Qt::QueuedConnection
,Q_ARG(A, a) );
return;
}
/* The actual work this function does would be below here... */
};
Some related thoughts:
I was contemplating to introduce a QMutexLocker before the if statement, but decided against it: the only part of the function that is potentially used in parallel (anything above the return; in the if statement) is--as far as I understand--thread safe.
Setting the connection type manually to Qt::QueuedConnection: technically, if I understand the documentation correctly, Qt should do the right thing and the default, Qt::AutoConnection, should end up becoming a Qt::QueuedConnection. But since would always be the case when that statement is reached, I decided to put explicitly in there to remind myself about why this is there.
putting the queuing code directly in the function and not hiding it in an interim function: I could have opted to put the call to invokeMethod in another interim function, say queueDoSomeWorkWithData()', which would be called by the callback in the listener and then usesinvokeMethodwith anQt::AutoConnection' on doSomeWorkWithData(). I decided against this as there seems no way for me to auto-code this interim function via templates (templates and the Meta system was part of the original problem), so "the user" of my code (i.e. the person who implements doSomeWorkWithData(XYZ xyz)) would have to hand type the interim function as well (as that is how the templated type names are correctly resolved). Including the check in the actual function seems to me to safe typing an extra function header, keeps the MyClass interface a little cleaner, and better reminds readers of doSomeWorkWithData() that there might be a threading issue lurking in the dark.
It is ok to call a public function on a subclass of QObject from another thread if you know for certain that the individual function will perform only thread-safe actions.
One nice thing about Qt is that it will handle foreign threads just as well as it handles QThreads. So, one option is to create a threadSafeDoSomeWorkWithData function for each doSomeWorkWithData that does nothing but QMetaMethod::invoke the non-threadsafe one.
public:
void threadSafeDoSomeWorkWithData(A a) {
QMetaMethod::invoke("doSomeWorkWithData", Q_ARG(A,a));
}
Q_INVOKABLE void doSomeWorkWithData(A a);
Alternatively, Sergey Tachenov suggests an interesting way of doing more or less the same thing in his answer here. He combines the two functions I suggested into one.
void Obj2::ping() {
if (QThread::currentThread() != this->thread()) {
// not sure how efficient it is
QMetaObject::invoke(this, "ping", Qt::QueuedConnection);
return;
}
// thread unsafe code goes here
}
As to why you see normal behaviour when not creating a GUI? Perhaps you're not doing anything else that is unsafe, aside from manipulating GUI objects. Or, perhaps they're the only place in which your thread-safety problems are obvious.

Resources