in remote/communicator.js [57:203]
constructor(channelProxy, options) {
if (!isChannelProxy(channelProxy)) {
throw new Error("channelProxy must be a IChannelProxy object.");
}
super();
/**
* @private
* @type {Array.<IRoute>}
*/
this.routes = [];
/**
* @private
* @type {Object.<string, IPromiseResolver>}
*/
this.ongoingPromiseDict = Object.create(null);
/**
* @public
* @readonly
* @type {string}
*/
this.id = random.generateUid(6);
if (options) {
if (utils.isString(options.id)
&& !utils.string.isEmptyOrWhitespace(options.id)) {
this.id = options.id;
}
if (utils.isNumber(options.timeout)) {
/**
* @readonly
* @type {number}
*/
this.timeout = options.timeout;
}
}
/**
* @private
* @type {Donuts.Remote.IChannelProxy}
*/
this.channelProxy = channelProxy;
/**
* @private
* @param {Donuts.Remote.IChannelProxy} channel
* @param {Donuts.Remote.IMessage} msg
* @returns {Promise<void>}
*/
this.onMessageAsync = async (channel, msg) => {
const promise = this.ongoingPromiseDict[msg.id];
/** @type {number} */
const receivedTimestamp = Date.now();
Log.writeInfoAsync("{} REMOTE {,7} {} ~{,4:F0}ms <= {}:{}", this.id, Action.Receive, msg.id, receivedTimestamp - msg.timestamp, msg.sender, msg.path);
if (promise) {
delete this.ongoingPromiseDict[msg.id];
msg.succeeded ? promise.resolve(msg.body) : promise.reject(msg.body);
} else if (utils.isNullOrUndefined(msg.succeeded)) {
/** @type {Donuts.Remote.IRoutePathInfo} */
let pathInfo;
/** @type {Donuts.Remote.AsyncRequestHandler} */
let asyncHandler;
// Find the corresponding route and
// generate the pathInfo.
for (const route of this.routes) {
asyncHandler = route.asyncHandler;
pathInfo = route.pattern.match(msg.path);
if (pathInfo) {
break;
}
}
if (!pathInfo) {
return;
}
/** @type {*} */
let response;
/** @type {boolean} */
let succeeded;
try {
response = await asyncHandler(this, pathInfo, msg.body);
succeeded = true;
} catch (exception) {
response = exception;
succeeded = false;
// @ts-ignore
if (response instanceof Error && !response["toJSON"]) {
// @ts-ignore
response.toJSON = ErrorToJSON;
}
}
/** @type {Donuts.Remote.IMessage} */
const responseMsg = {
id: msg.id,
sender: this.id,
timestamp: Date.now(),
path: msg.path,
succeeded: succeeded,
body: response
};
Log.writeInfoAsync("{} REMOTE {,7} {} ~{,4:F0}ms => {}:{}", this.id, Action.Respond, responseMsg.id, responseMsg.timestamp - receivedTimestamp, msg.sender, msg.path);
this.channelProxy.sendData(responseMsg);
}
};
/**
* @private
* @param {Donuts.Remote.IChannelProxy} proxy
* @return {void}
*/
this.onClose = (proxy) => {
this.emit("close", this);
};
/**
* @private
* @param {Donuts.Remote.IChannelProxy} proxy
* @param {Error} err
* @return {void}
*/
this.onError = (proxy, err) => {
this.emit("error", this, err);
};
this.channelProxy.setHandler("data", this.onMessageAsync);
this.channelProxy.setHandler("close", this.onClose);
this.channelProxy.setHandler("error", this.onError);
}