Browse Source

Add a `waitUntil` API for promises.

JC Brand 8 years ago
parent
commit
994c961d9c
4 changed files with 67 additions and 2 deletions
  1. 1 0
      docs/CHANGES.md
  2. 41 1
      docs/source/developer_api.rst
  3. 7 0
      src/converse-api.js
  4. 18 1
      src/converse-core.js

+ 1 - 0
docs/CHANGES.md

@@ -9,6 +9,7 @@
 - Use lodash instead of underscore.js [jcbrand]
 - Use lodash instead of underscore.js [jcbrand]
 - Improved roster filter UX. [jcbrand]
 - Improved roster filter UX. [jcbrand]
 - Render the login form again upon authfail. [jcbrand]
 - Render the login form again upon authfail. [jcbrand]
+- New promises API: [waitUntil](https://conversejs.org/docs/html/developer_api.html#waituntil) [jcbrand]
 - #770 Allow setting contact attrs on chats.open [Ape]
 - #770 Allow setting contact attrs on chats.open [Ape]
 
 
 ## 2.0.6 (2017-02-13)
 ## 2.0.6 (2017-02-13)

+ 41 - 1
docs/source/developer_api.rst

@@ -1,7 +1,7 @@
 .. raw:: html
 .. raw:: html
 
 
     <div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
     <div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
- 
+
 =============================
 =============================
 The converse.js developer API
 The converse.js developer API
 =============================
 =============================
@@ -84,6 +84,7 @@ Example:
             roster_groups: true
             roster_groups: true
         });
         });
 
 
+
 The **plugin** grouping
 The **plugin** grouping
 ------------------------
 ------------------------
 
 
@@ -164,6 +165,44 @@ For example, to send a message stanza:
     });
     });
 
 
 
 
+.. _`waituntil-grouping`:
+
+waitUntil
+---------
+
+This method can be used to wait for promises. Promises are similar to events
+(for event handling, refer to the :ref:`listen-grouping`), but they differ in
+two important ways:
+
+* A promise gets resolved only once, whereas events can fire multiple times.
+* A handler registered for a promise, will still fire *after* the promise has
+  been resolved, which is not the case with an event handler.
+
+Converse.js has the following promises:
+
+* cachedRoster
+* chatBoxesFetched
+* connected
+* pluginsInitialized
+* roster
+* rosterContactsFetched
+* rosterGroupsFetched
+* rosterInitialized
+* statusInitialized
+
+Below is an example from `converse-muc.js <https://github.com/jcbrand/converse.js/blob/master/src/converse-muc.js>`_
+where the `rosterContactsFetched` promise is waited on. The method
+`this.initInviteWidget` will initialize the chatroom invitation widget.
+
+.. code-block:: javascript
+
+    _converse.api.waitUntil('rosterContactsFetched').then(this.initInviteWidget.bind(this));
+
+The line above executes only once a chatroom has been opened and entered, so
+using an event handler here would not work, since the event might have fired
+already by that time.
+
+
 The **archive** grouping
 The **archive** grouping
 ------------------------
 ------------------------
 
 
@@ -982,3 +1021,4 @@ grouping:
 .. code-block:: javascript
 .. code-block:: javascript
 
 
         _converse.listen.not('message', function (messageXML) { ... });
         _converse.listen.not('message', function (messageXML) { ... });
+

+ 7 - 0
src/converse-api.js

@@ -180,6 +180,13 @@
                 );
                 );
             },
             },
         },
         },
+        'waitUntil': function (name) {
+            var promise = _converse.promises[name];
+            if (_.isUndefined(promise)) {
+                return null;
+            }
+            return _converse.promises[name].promise();
+        },
         'send': function (stanza) {
         'send': function (stanza) {
             _converse.connection.send(stanza);
             _converse.connection.send(stanza);
         },
         },

+ 18 - 1
src/converse-core.js

@@ -47,7 +47,24 @@
     var _converse = {};
     var _converse = {};
     _converse.templates = {};
     _converse.templates = {};
     _.extend(_converse, Backbone.Events);
     _.extend(_converse, Backbone.Events);
-    _converse.emit = _converse.trigger;
+    _converse.promises = {
+        'cachedRoster': new $.Deferred(),
+        'chatBoxesFetched': new $.Deferred(),
+        'connected': new $.Deferred(),
+        'pluginsInitialized': new $.Deferred(),
+        'roster': new $.Deferred(),
+        'rosterContactsFetched': new $.Deferred(),
+        'rosterGroupsFetched': new $.Deferred(),
+        'rosterInitialized': new $.Deferred(),
+        'statusInitialized': new $.Deferred()
+    };
+    _converse.emit = function (name) {
+        _converse.trigger.apply(this, arguments);
+        var promise = _converse.promises[name];
+        if (!_.isUndefined(promise)) {
+            promise.resolve();
+        }
+    };
 
 
     _converse.core_plugins = [
     _converse.core_plugins = [
         'converse-bookmarks',
         'converse-bookmarks',