修改公共 npm 包中的某些功能
Modifying some features in a public npm package
我正在尝试重载/替换ami-io
npm 包中的函数。创建该包是为了与星号 AMI(套接字接口(通信。
我需要与具有几乎完全相同界面的服务通信,但它在登录时显示不同的问候字符串,并且需要在登录中增加一个字段。其余的都是一样的。我不只是简单地复制 600 LOC ami-io
包并修改两三行,而是要覆盖检测问候字符串的函数和登录函数,并继续使用 ami-io
包。
在ami-io
包中有一个文件index.js
其中包含以下功能:
Client.prototype.auth = function (data) {
this.logger.debug('First message:', data);
if (data.match(/Asterisk Call Manager/)) {
this._setVersion(data);
this.socket.on('data', function (data) {
this.splitMessages(data);
}.bind(this));
this.send(new Action.Login(this.config.login, this.config.password), function (error, response) {
if (response && response.response === 'Success') this.emit('connected');
else this.emit('incorrectLogin');
}.bind(this));
} else {
this.emit('incorrectServer', data);
}
};
现在我不想在Asterisk Call Manager
上匹配,而是在MyService
上匹配,我想定义并使用带有额外参数的另一个Action.LoginExt(this.config.login, this.config.password)
。
这可能吗?我在自己的模块中尝试了这个:
var AmiIo = require('ami-io');
var amiio = AmiIo.createClient({port:5038, host:'x.x.x.x', login:'system', password:'admin'});
amiio.prototype.auth = function (data) {
this.logger.debug('First message:', data);
if (data.match(/MyService Version/)) {
this._setVersion(data);
this.socket.on('data', function (data) {
this.splitMessages(data);
}.bind(this));
this.send(new Action.LoginExt(this.config.login, this.config.password, this.config.extra), function (error, response) {
if (response && response.response === 'Success') this.emit('connected');
else this.emit('incorrectLogin');
}.bind(this));
} else {
this.emit('incorrectServer', data);
}
};
。但它导致了TypeError: Cannot set property 'auth' of undefined
,现在我毫无头绪。另外,我可以在自己的模块中定义一个新的Action.LoginExt
对象吗?如何?
action.js 模块按如下方式定义 Action 对象:
function Action(name) {
Action.super_.bind(this)();
this.id = this.getId();
this.set('ActionID', this.id);
this.set('Action', name);
}
(function(){
var Message = require('./message.js');
var util = require('util');
util.inherits(Action, Message);
})();
Action.prototype.getId = (function() {
var id = 0;
return function() {
return ++id;
}
})();
function Login(username, secret) {
Login.super_.bind(this, 'Login')();
this.set('Username', username);
this.set('Secret', secret );
}
... more functions ...
(function() {
var actions = [
Login,
... more functions ...
];
var util = require('util');
for (var i = 0; i < actions.length; i++) {
util.inherits(actions[i], Action);
exports[actions[i].name] = actions[i];
}
exports.Action = Action;
})();
我想我理解的是,操作是从消息中子类化的。Login 函数又从 Action 中子类化,并导出(在最后一个代码块中(。所以我认为在我的代码中我可以尝试类似的东西:
// extend ami-io with LoginExt function
function LoginExt(username, secret, company) {
Login.super_.bind(this, 'LoginExt')();
this.set('Username', username);
this.set('Secret', secret );
this.set('Company', company);
}
var util = require('util');
util.inherits(LoginExt, amiio.Action);
但是util.inherits失败了,没有定义。我还在ami-io上打开了一个问题。
您可以使用:
var AmiIo = require('ami-io');
AmiIo.Action.Login = function NewConstructor(){}; //to override Login action
//new constructor shold extend AmiIo.Action.Action(actionName)
//and also, you can use
AmiIo.Action.SomeNewAction = function SomeNewAction(){};//to create new actuion
//it also should extend AmiIo.Action.Action(actionName);
AmiIo.Action只是一个对象。所有构造函数都是它的字段。
要创建新事件,您无需执行任何操作,因为它只是一个对象。如果服务器发送给您
Event: Armageddon
SomeField: 123
ami-io 将创建名为 'Armageddon'
的事件。
要覆盖 Client#auth(( 方法,您应该这样做
var AmiIo = require('ami-io');
AmiIo.Client.prototype.auth = function (){};//new function
amiio
是Client
的一个实例。prototype
属性仅对构造函数(如 Client
(有意义。它对构造函数的结果没有意义(除非在不常见的情况下,实例恰好也是一个函数本身 - 但即使在这种情况下,更改实例的prototype
也不会影响其父构造函数(。
相反,您需要使用以下Object.getPrototypeOf
获取实例的原型:
Object.getPrototypeOf(amiio).auth = function() { ... }
如果不需要为每个客户端更改此设置,而只需要更改单个客户端,则根本不需要更改原型。更改实例的auth
就足够了:
amiio.auth = function() { ... }
请注意,如果Action.LoginExt
是模块范围的本地代码,则代码将不起作用。如果模块导出它,您可能可以改为执行AmiIo.Action.LoginExt
。如果它不导出LoginExt
,则需要复制实现它的代码,然后在导入范围内重新实现它。修改模块本身可能更简单。
这是我应用的解决方案
:// Override the AmiIo auth procedure, because the other login is slightly different
// Write our own Login function (which adds a company)
function Login(username, secret, company) {
Login.super_.bind(this, 'Login')();
this.set('Username', username);
this.set('Secret', secret );
this.set('Company', company);
}
// This function should inherit from Action
var util = require('util');
util.inherits(Login, AmiIo.Action.Action);
AmiIo.Action.Login = Login;
// replace the auth with our own, to add the company. Also
// this sends a slightly different greeting: "Service Version 1.0"
AmiIo.Client.prototype.auth = function (data) {
if (data.match(/Service Version/)) {
this._setVersion(data);
this.socket.on('data', function (data) {
this.splitMessages(data);
}.bind(this));
this.send(new AmiIo.Action.Login(this.config.login, this.config.password, this.config.company), function (error, response) {
if (response && response.response === 'Success') this.emit('connected');
else this.emit('incorrectLogin');
}.bind(this));
} else {
this.emit('incorrectServer', data);
}
};
// our own function to grab the version number from the new greeting
AmiIo.Client.prototype._setVersion = function(version){
var v = version.match(/Service Version (['d'.]*['-'w'd'.]*)/i);
if (v){
this.version = v[1];
}
};
所以事实证明,这和我希望的一样可行。@NumminorihSF和@apsillers的回答都在这里帮助了我,但我只能将其中一个标记为最佳答案。
- 在自定义mean.io包中使用angular-chart.js作为依赖项
- 有没有办法限制Meteor-alded表格包中已发布的字段
- 如何在Yii2资产捆绑包中使用JSX文件
- 如何在Angularjs中重构闭包中的重复代码
- 如何冻结函数's在闭包中的变量
- 局部变量在闭包中丢失
- 闭包中的Javascript值
- javascript,将参数传递给函数内部的闭包中的回调
- 其中是闭包中存储的变量-堆栈或堆
- Ajax控制工具包中的错误's升级后的JS文件
- jQuery Div滚动功能:IE中的问题
- 如何使用浏览器“需要”配置文件,但不将此文件包含在捆绑包中
- webpack 将 CSS 作为字符串内联到 JS 捆绑包中
- var 函数名称与函数闭包中的名称分配
- 何时在闭包中使用 typedef
- 节点包中的“需要”钩子
- Javascript,闭包中的返回函数如何与外部函数连接
- Javascript:附加字符串中的事件,闭包中的变量求值
- 循环/闭包中的JavaScript函数
- 修改公共 npm 包中的某些功能