mirror of
https://github.com/jupyter/notebook.git
synced 2025-01-12 11:45:38 +08:00
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:
parent
10dcd71550
commit
0169ce472e
@ -41,6 +41,7 @@ define([
|
|||||||
this.username = "username";
|
this.username = "username";
|
||||||
this.session_id = utils.uuid();
|
this.session_id = utils.uuid();
|
||||||
this._msg_callbacks = {};
|
this._msg_callbacks = {};
|
||||||
|
this._msg_queue = Promise.resolve();
|
||||||
this.info_reply = {}; // kernel_info_reply stored here after starting
|
this.info_reply = {}; // kernel_info_reply stored here after starting
|
||||||
|
|
||||||
if (typeof(WebSocket) !== 'undefined') {
|
if (typeof(WebSocket) !== 'undefined') {
|
||||||
@ -854,7 +855,10 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
Kernel.prototype._handle_ws_message = function (e) {
|
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) {
|
Kernel.prototype._finish_ws_message = function (msg) {
|
||||||
|
@ -30,7 +30,7 @@ define([
|
|||||||
return msg;
|
return msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
var _deserialize_binary = function(data, callback) {
|
var _deserialize_binary = function(data) {
|
||||||
/**
|
/**
|
||||||
* deserialize the binary message format
|
* deserialize the binary message format
|
||||||
* callback will be called with a message whose buffers attribute
|
* callback will be called with a message whose buffers attribute
|
||||||
@ -39,28 +39,31 @@ define([
|
|||||||
if (data instanceof Blob) {
|
if (data instanceof Blob) {
|
||||||
// data is Blob, have to deserialize from ArrayBuffer in reader callback
|
// data is Blob, have to deserialize from ArrayBuffer in reader callback
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
reader.onload = function () {
|
var promise = new Promise(function(resolve, reject) {
|
||||||
var msg = _deserialize_array_buffer(this.result);
|
reader.onload = function () {
|
||||||
callback(msg);
|
var msg = _deserialize_array_buffer(this.result);
|
||||||
};
|
resolve(msg);
|
||||||
|
};
|
||||||
|
});
|
||||||
reader.readAsArrayBuffer(data);
|
reader.readAsArrayBuffer(data);
|
||||||
|
return promise;
|
||||||
} else {
|
} else {
|
||||||
// data is ArrayBuffer, can deserialize directly
|
// data is ArrayBuffer, can deserialize directly
|
||||||
var msg = _deserialize_array_buffer(data);
|
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") {
|
if (typeof data === "string") {
|
||||||
// text JSON message
|
// text JSON message
|
||||||
callback(JSON.parse(data));
|
return Promise.resolve(JSON.parse(data));
|
||||||
} else {
|
} else {
|
||||||
// binary message
|
// binary message
|
||||||
_deserialize_binary(data, callback);
|
return Promise.resolve(_deserialize_binary(data));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,4 +120,4 @@ define([
|
|||||||
serialize: serialize
|
serialize: serialize
|
||||||
};
|
};
|
||||||
return exports;
|
return exports;
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user