Fix race condition in javascript kernel message processing

Because the binary messages are now deserialized using the asynchronous FileReader API, we need to have some way to force the messages to still be processed in the order they are received.  This patch implements a simple processing queue using promises.
This commit is contained in:
Jason Grout 2015-02-13 22:41:16 +00:00
parent 10dcd71550
commit 0169ce472e
2 changed files with 19 additions and 12 deletions

View File

@ -41,6 +41,7 @@ define([
this.username = "username";
this.session_id = utils.uuid();
this._msg_callbacks = {};
this._msg_queue = Promise.resolve();
this.info_reply = {}; // kernel_info_reply stored here after starting
if (typeof(WebSocket) !== 'undefined') {
@ -854,7 +855,10 @@ define([
};
Kernel.prototype._handle_ws_message = function (e) {
serialize.deserialize(e.data, $.proxy(this._finish_ws_message, this));
this._msg_queue = this._msg_queue.then(function() {
return serialize.deserialize(e.data);
}).then($.proxy(this._finish_ws_message, this))
.catch(utils.reject("Couldn't process kernel message", true));
};
Kernel.prototype._finish_ws_message = function (msg) {

View File

@ -30,7 +30,7 @@ define([
return msg;
};
var _deserialize_binary = function(data, callback) {
var _deserialize_binary = function(data) {
/**
* deserialize the binary message format
* callback will be called with a message whose buffers attribute
@ -39,28 +39,31 @@ define([
if (data instanceof Blob) {
// data is Blob, have to deserialize from ArrayBuffer in reader callback
var reader = new FileReader();
var promise = new Promise(function(resolve, reject) {
reader.onload = function () {
var msg = _deserialize_array_buffer(this.result);
callback(msg);
resolve(msg);
};
});
reader.readAsArrayBuffer(data);
return promise;
} else {
// data is ArrayBuffer, can deserialize directly
var msg = _deserialize_array_buffer(data);
callback(msg);
return msg;
}
};
var deserialize = function (data, callback) {
var deserialize = function (data) {
/**
* deserialize a message and pass the unpacked message object to callback
* deserialize a message and return a promise for the unpacked message
*/
if (typeof data === "string") {
// text JSON message
callback(JSON.parse(data));
return Promise.resolve(JSON.parse(data));
} else {
// binary message
_deserialize_binary(data, callback);
return Promise.resolve(_deserialize_binary(data));
}
};