2016-04-04 9 views
0

ami-io npmパッケージの機能をオーバーロード/置換しようとしています。このパッケージは、ソケットインタフェースであるアスタリスクAMIと通信するために作成されています。公開npmパッケージの一部の機能を変更しました

ほとんど同じインターフェイスを持つサービスと話す必要がありますが、ログイン時に別の挨拶文字列が表示され、ログオンに余分なフィールドが必要です。すべての残りは同じです。 600 LOC ami-ioパッケージを単純にコピーし、2行または3行を変更する代わりに、挨拶文字列とログイン機能を検出する関数をオーバーライドして、ami-ioパッケージを使用し続けます。

次の関数が含まれているファイルindex.jsありami-ioパッケージ内側:

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モジュールはアクションオブジェクトを定義しています

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にも問題を開いた。

答えて

1

あなたは使用することができます。

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'のイベントを作成します。クライアント#AUTH()メソッドをオーバーライドする

、あなただけの

var AmiIo = require('ami-io'); 
AmiIo.Client.prototype.auth = function(){};//new function 
0

amiioは、のインスタンスClientです。 prototypeプロパティは、Clientなどのコンストラクタ関数でのみ意味があります。コンストラクタ関数の結果では意味がありません(インスタンスが関数そのものでもあるという例外的な場合を除きますが、その場合でもインスタンスのprototypeを変更してもその親コン​​ストラクタには影響しません)。

代わりに、あなたはObject.getPrototypeOfとインスタンスのプロトタイプを取得する必要があります:

Object.getPrototypeOf(amiio).auth = function() { ... } 

あなたはすべてのクライアントのためにこれを変更する必要があるが、唯一の単一のクライアントでない場合は、変更する必要はありませんプロトタイプはまったくありません。インスタンスのauthが十分にある変更:Action.LoginExtは、モジュールのスコープに対してローカルである場合、あなたのコードは動作しません

amiio.auth = function() { ... } 

注意。モジュールがそれをエクスポートする場合は、おそらくAmiIo.Action.LoginExtを実行することができます。 LoginExtをエクスポートしない場合は、それを実装するコードをコピーして、インポートスコープに再実装する必要があります。モジュール自体を変更する方が簡単かもしれません。

+0

ありがとうございました。それはとても簡単です。私は今、アクションを追加/拡張することで取り組んでいます。実際には、モジュール自体を変更する方が簡単かもしれませんが、技術的負債を生み出す私自身のコードベースに取り込む必要があります。または、forkして名前を変更し、npm repoに入れます。ほんの数行のコードの場合 – raarts

0

を行う必要がありますここで私が働いていることを塗布された溶液です:

// 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の両方の回答が私の助けになりましたが、そのうちの1つだけを最良の回答としてマークすることができました。

関連する問題