如何创建一个 returns 等待 EventEmitter 的 promise 的函数?
How to create a function that returns a promise which waits for an EventEmitter?
当使用使用 EventEmitters
来指示调用启动函数后返回结果的 JS 库时,如何使用调用启动函数的函数包装库,然后 returns 等待发射事件的 Promise?
更新:本例中使用唯一标识符匹配请求与返回结果。
例如:
var Class = (function() {
Class = function() {
self = this
self.transactionid = undefined
self.result = undefined
self.client = new Client({
clientId: 0,
host: '127.0.0.1',
port: 4001
}).on('received', function (tokens) {
console.info('%s %s', '<<< RECV <<<'.cyan, JSON.stringify(tokens))
// I wish to return `tokens` here via the promise
if( tokens[ 0 ] == self.transactionid )
self.result = tokens[ 1 ]
}).on('sent', function (tokens) {
console.info('%s %s', '>>> SENT >>>'.yellow, JSON.stringify(tokens))
})
self.client.connect()
}
Class.prototype.request = function( id ) {
return $q( function( resolve, reject ) {
self.transactionid = 1000
self.client.requestData( transactionid, { key: '1234' }, '', false)
var data = '<want to wait for / return token data here>'
// possibly use a dictionary to track different transactions and results?
resolve( data )
})
}
return Class
})()
如果您将 "return tokens
via the promise" 改写为 "resolve a Deferred associated with this transaction id",那么您最终会得到非常类似于常规 promise 缓存的东西 - 除了此处需要延迟缓存。
幸运的是,$q(类似于 Q 但不同于 Bluebird 或原生 promises)为这种情况提供了 Deferreds,其中 Promise 创建和 Promise 结算是松散耦合或错位的。
var Class = (function() {
Class = function() {
self = this;
self.transactions = {}; // a cache of Deferred objects
self.client = new Client({
clientId: 0,
host: '127.0.0.1',
port: 4001
}).on('received', function (tokens) {
console.info('%s %s', '<<< RECV <<<'.cyan, JSON.stringify(tokens));
self.transactions[tokens[0]].resolve(tokens[1]);
}).on('sent', function(tokens) {
console.info('%s %s', '>>> SENT >>>'.yellow, JSON.stringify(tokens));
});
self.client.connect();
};
Class.prototype.request = function(id) {
if(!this.transactions[id]) {
this.transactions[id] = $q.defer();// a Deferred object to be deferred in the onReceived handler
this.client.requestData( id, { key: '1234' }, '', false);
}
return this.transactions[id].promise;
}
return Class;
})();
错误处理似乎是一个更大的问题。您可以重新引入一个 onerror 处理程序,但除非它的 error
对象包含一个 id
属性,否则您没有密钥从 this.transactions
中检索相应的 Deferred。
所以,要么:
- 修改 Client() class 以传送带有
id
属性 的错误对象。
- 在创建请求的地方,在超时后拒绝 Deferred。
甚至以上两者。
当使用使用 EventEmitters
来指示调用启动函数后返回结果的 JS 库时,如何使用调用启动函数的函数包装库,然后 returns 等待发射事件的 Promise?
更新:本例中使用唯一标识符匹配请求与返回结果。
例如:
var Class = (function() {
Class = function() {
self = this
self.transactionid = undefined
self.result = undefined
self.client = new Client({
clientId: 0,
host: '127.0.0.1',
port: 4001
}).on('received', function (tokens) {
console.info('%s %s', '<<< RECV <<<'.cyan, JSON.stringify(tokens))
// I wish to return `tokens` here via the promise
if( tokens[ 0 ] == self.transactionid )
self.result = tokens[ 1 ]
}).on('sent', function (tokens) {
console.info('%s %s', '>>> SENT >>>'.yellow, JSON.stringify(tokens))
})
self.client.connect()
}
Class.prototype.request = function( id ) {
return $q( function( resolve, reject ) {
self.transactionid = 1000
self.client.requestData( transactionid, { key: '1234' }, '', false)
var data = '<want to wait for / return token data here>'
// possibly use a dictionary to track different transactions and results?
resolve( data )
})
}
return Class
})()
如果您将 "return tokens
via the promise" 改写为 "resolve a Deferred associated with this transaction id",那么您最终会得到非常类似于常规 promise 缓存的东西 - 除了此处需要延迟缓存。
幸运的是,$q(类似于 Q 但不同于 Bluebird 或原生 promises)为这种情况提供了 Deferreds,其中 Promise 创建和 Promise 结算是松散耦合或错位的。
var Class = (function() {
Class = function() {
self = this;
self.transactions = {}; // a cache of Deferred objects
self.client = new Client({
clientId: 0,
host: '127.0.0.1',
port: 4001
}).on('received', function (tokens) {
console.info('%s %s', '<<< RECV <<<'.cyan, JSON.stringify(tokens));
self.transactions[tokens[0]].resolve(tokens[1]);
}).on('sent', function(tokens) {
console.info('%s %s', '>>> SENT >>>'.yellow, JSON.stringify(tokens));
});
self.client.connect();
};
Class.prototype.request = function(id) {
if(!this.transactions[id]) {
this.transactions[id] = $q.defer();// a Deferred object to be deferred in the onReceived handler
this.client.requestData( id, { key: '1234' }, '', false);
}
return this.transactions[id].promise;
}
return Class;
})();
错误处理似乎是一个更大的问题。您可以重新引入一个 onerror 处理程序,但除非它的 error
对象包含一个 id
属性,否则您没有密钥从 this.transactions
中检索相应的 Deferred。
所以,要么:
- 修改 Client() class 以传送带有
id
属性 的错误对象。 - 在创建请求的地方,在超时后拒绝 Deferred。
甚至以上两者。