##// END OF EJS Templates
Promise the messages to the model
Jonathan Frederic -
Show More
@@ -1,193 +1,202 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'base/js/utils',
7 'base/js/utils',
8 ], function(IPython, $, utils) {
8 ], function(IPython, $, utils) {
9 "use strict";
9 "use strict";
10
10
11 //-----------------------------------------------------------------------
11 //-----------------------------------------------------------------------
12 // CommManager class
12 // CommManager class
13 //-----------------------------------------------------------------------
13 //-----------------------------------------------------------------------
14
14
15 var CommManager = function (kernel) {
15 var CommManager = function (kernel) {
16 this.comms = {};
16 this.comms = {};
17 this.targets = {};
17 this.targets = {};
18 if (kernel !== undefined) {
18 if (kernel !== undefined) {
19 this.init_kernel(kernel);
19 this.init_kernel(kernel);
20 }
20 }
21 };
21 };
22
22
23 CommManager.prototype.init_kernel = function (kernel) {
23 CommManager.prototype.init_kernel = function (kernel) {
24 // connect the kernel, and register message handlers
24 // connect the kernel, and register message handlers
25 this.kernel = kernel;
25 this.kernel = kernel;
26 var msg_types = ['comm_open', 'comm_msg', 'comm_close'];
26 var msg_types = ['comm_open', 'comm_msg', 'comm_close'];
27 for (var i = 0; i < msg_types.length; i++) {
27 for (var i = 0; i < msg_types.length; i++) {
28 var msg_type = msg_types[i];
28 var msg_type = msg_types[i];
29 kernel.register_iopub_handler(msg_type, $.proxy(this[msg_type], this));
29 kernel.register_iopub_handler(msg_type, $.proxy(this[msg_type], this));
30 }
30 }
31 };
31 };
32
32
33 CommManager.prototype.new_comm = function (target_name, data, callbacks, metadata) {
33 CommManager.prototype.new_comm = function (target_name, data, callbacks, metadata) {
34 // Create a new Comm, register it, and open its Kernel-side counterpart
34 // Create a new Comm, register it, and open its Kernel-side counterpart
35 // Mimics the auto-registration in `Comm.__init__` in the IPython Comm
35 // Mimics the auto-registration in `Comm.__init__` in the IPython Comm
36 var comm = new Comm(target_name);
36 var comm = new Comm(target_name);
37 this.register_comm(comm);
37 this.register_comm(comm);
38 comm.open(data, callbacks, metadata);
38 comm.open(data, callbacks, metadata);
39 return comm;
39 return comm;
40 };
40 };
41
41
42 CommManager.prototype.register_target = function (target_name, f) {
42 CommManager.prototype.register_target = function (target_name, f) {
43 // Register a target function for a given target name
43 // Register a target function for a given target name
44 this.targets[target_name] = f;
44 this.targets[target_name] = f;
45 };
45 };
46
46
47 CommManager.prototype.unregister_target = function (target_name, f) {
47 CommManager.prototype.unregister_target = function (target_name, f) {
48 // Unregister a target function for a given target name
48 // Unregister a target function for a given target name
49 delete this.targets[target_name];
49 delete this.targets[target_name];
50 };
50 };
51
51
52 CommManager.prototype.register_comm = function (comm) {
52 CommManager.prototype.register_comm = function (comm) {
53 // Register a comm in the mapping
53 // Register a comm in the mapping
54 this.comms[comm.comm_id] = comm;
54 this.comms[comm.comm_id] = comm;
55 comm.kernel = this.kernel;
55 comm.kernel = this.kernel;
56 return comm.comm_id;
56 return comm.comm_id;
57 };
57 };
58
58
59 CommManager.prototype.unregister_comm = function (comm) {
59 CommManager.prototype.unregister_comm = function (comm) {
60 // Remove a comm from the mapping
60 // Remove a comm from the mapping
61 delete this.comms[comm.comm_id];
61 delete this.comms[comm.comm_id];
62 };
62 };
63
63
64 // comm message handlers
64 // comm message handlers
65
65
66 CommManager.prototype.comm_open = function (msg) {
66 CommManager.prototype.comm_open = function (msg) {
67 var content = msg.content;
67 var content = msg.content;
68 var that = this;
68 var that = this;
69
69
70 return utils.load_class(content.target_name, content.target_module,
70 return utils.load_class(content.target_name, content.target_module,
71 this.targets).then(function(target) {
71 this.targets).then(function(target) {
72
72
73 var comm = new Comm(content.target_name, content.comm_id);
73 var comm = new Comm(content.target_name, content.comm_id);
74 that.register_comm(comm);
74 that.register_comm(comm);
75 try {
75 try {
76 target(comm, msg);
76 target(comm, msg);
77 } catch (e) {
77 } catch (e) {
78 comm.close();
78 comm.close();
79 that.unregister_comm(comm);
79 that.unregister_comm(comm);
80 var wrapped_error = new utils.WrappedError("Exception opening new comm", e);
80 var wrapped_error = new utils.WrappedError("Exception opening new comm", e);
81 console.error(wrapped_error);
81 console.error(wrapped_error);
82 return Promise.reject(wrapped_error);
82 return Promise.reject(wrapped_error);
83 }
83 }
84 return comm;
84 return comm;
85 }, utils.reject('Could not open comm', true));
85 }, utils.reject('Could not open comm', true));
86 };
86 };
87
87
88 CommManager.prototype.comm_close = function (msg) {
88 CommManager.prototype.comm_close = function (msg) {
89 var content = msg.content;
89 var content = msg.content;
90 var comm = this.comms[content.comm_id];
90 var comm = this.comms[content.comm_id];
91 if (comm === undefined) {
91 if (comm === undefined) {
92 return;
92 return;
93 }
93 }
94 this.unregister_comm(comm);
94 this.unregister_comm(comm);
95 try {
95 try {
96 comm.handle_close(msg);
96 comm.handle_close(msg);
97 } catch (e) {
97 } catch (e) {
98 console.log("Exception closing comm: ", e, e.stack, msg);
98 console.log("Exception closing comm: ", e, e.stack, msg);
99 }
99 }
100 };
100 };
101
101
102 CommManager.prototype.comm_msg = function (msg) {
102 CommManager.prototype.comm_msg = function (msg) {
103 var content = msg.content;
103 var content = msg.content;
104 var comm = this.comms[content.comm_id];
104 var comm = this.comms[content.comm_id];
105 if (comm === undefined) {
105 if (comm === undefined) {
106 return;
106 return;
107 }
107 }
108 try {
108 try {
109 comm.handle_msg(msg);
109 comm.handle_msg(msg);
110 } catch (e) {
110 } catch (e) {
111 console.log("Exception handling comm msg: ", e, e.stack, msg);
111 console.log("Exception handling comm msg: ", e, e.stack, msg);
112 }
112 }
113 };
113 };
114
114
115 //-----------------------------------------------------------------------
115 //-----------------------------------------------------------------------
116 // Comm base class
116 // Comm base class
117 //-----------------------------------------------------------------------
117 //-----------------------------------------------------------------------
118
118
119 var Comm = function (target_name, comm_id) {
119 var Comm = function (target_name, comm_id) {
120 this.target_name = target_name;
120 this.target_name = target_name;
121 this.comm_id = comm_id || utils.uuid();
121 this.comm_id = comm_id || utils.uuid();
122 this._msg_callback = this._close_callback = null;
122 this._msg_callback = this._close_callback = null;
123
124 var that = this;
125 this.msg_promise = new Promise(function(resolve, reject) {
126 that.resolve_msg_promise = resolve;
127 });
123 };
128 };
124
129
125 // methods for sending messages
130 // methods for sending messages
126 Comm.prototype.open = function (data, callbacks, metadata) {
131 Comm.prototype.open = function (data, callbacks, metadata) {
127 var content = {
132 var content = {
128 comm_id : this.comm_id,
133 comm_id : this.comm_id,
129 target_name : this.target_name,
134 target_name : this.target_name,
130 data : data || {},
135 data : data || {},
131 };
136 };
132 return this.kernel.send_shell_message("comm_open", content, callbacks, metadata);
137 return this.kernel.send_shell_message("comm_open", content, callbacks, metadata);
133 };
138 };
134
139
135 Comm.prototype.send = function (data, callbacks, metadata, buffers) {
140 Comm.prototype.send = function (data, callbacks, metadata, buffers) {
136 var content = {
141 var content = {
137 comm_id : this.comm_id,
142 comm_id : this.comm_id,
138 data : data || {},
143 data : data || {},
139 };
144 };
140 return this.kernel.send_shell_message("comm_msg", content, callbacks, metadata, buffers);
145 return this.kernel.send_shell_message("comm_msg", content, callbacks, metadata, buffers);
141 };
146 };
142
147
143 Comm.prototype.close = function (data, callbacks, metadata) {
148 Comm.prototype.close = function (data, callbacks, metadata) {
144 var content = {
149 var content = {
145 comm_id : this.comm_id,
150 comm_id : this.comm_id,
146 data : data || {},
151 data : data || {},
147 };
152 };
148 return this.kernel.send_shell_message("comm_close", content, callbacks, metadata);
153 return this.kernel.send_shell_message("comm_close", content, callbacks, metadata);
149 };
154 };
150
155
151 // methods for registering callbacks for incoming messages
156 // methods for registering callbacks for incoming messages
152 Comm.prototype._register_callback = function (key, callback) {
157 Comm.prototype._register_callback = function (key, callback) {
153 this['_' + key + '_callback'] = callback;
158 this['_' + key + '_callback'] = callback;
154 };
159 };
155
160
156 Comm.prototype.on_msg = function (callback) {
161 Comm.prototype.on_msg = function (callback) {
157 this._register_callback('msg', callback);
162 this._register_callback('msg', callback);
163 this.resolve_msg_promise();
158 };
164 };
159
165
160 Comm.prototype.on_close = function (callback) {
166 Comm.prototype.on_close = function (callback) {
161 this._register_callback('close', callback);
167 this._register_callback('close', callback);
162 };
168 };
163
169
164 // methods for handling incoming messages
170 // methods for handling incoming messages
165
171
166 Comm.prototype._maybe_callback = function (key, msg) {
172 Comm.prototype._maybe_callback = function (key, msg) {
167 var callback = this['_' + key + '_callback'];
173 var callback = this['_' + key + '_callback'];
168 if (callback) {
174 if (callback) {
169 try {
175 try {
170 callback(msg);
176 callback(msg);
171 } catch (e) {
177 } catch (e) {
172 console.log("Exception in Comm callback", e, e.stack, msg);
178 console.log("Exception in Comm callback", e, e.stack, msg);
173 }
179 }
174 }
180 }
175 };
181 };
176
182
177 Comm.prototype.handle_msg = function (msg) {
183 Comm.prototype.handle_msg = function (msg) {
178 this._maybe_callback('msg', msg);
184 var that = this;
185 this.msg_promise.then(function() {
186 that._maybe_callback('msg', msg);
187 });
179 };
188 };
180
189
181 Comm.prototype.handle_close = function (msg) {
190 Comm.prototype.handle_close = function (msg) {
182 this._maybe_callback('close', msg);
191 this._maybe_callback('close', msg);
183 };
192 };
184
193
185 // For backwards compatability.
194 // For backwards compatability.
186 IPython.CommManager = CommManager;
195 IPython.CommManager = CommManager;
187 IPython.Comm = Comm;
196 IPython.Comm = Comm;
188
197
189 return {
198 return {
190 'CommManager': CommManager,
199 'CommManager': CommManager,
191 'Comm': Comm
200 'Comm': Comm
192 };
201 };
193 });
202 });
General Comments 0
You need to be logged in to leave comments. Login now