Javascript 预示溪流
我试图向你保证,但这似乎比我想象的要难。以下是我的尝试:Javascript 预示溪流,javascript,node.js,promise,eventemitter,Javascript,Node.js,Promise,Eventemitter,我试图向你保证,但这似乎比我想象的要难。以下是我的尝试: 'use strict' const Promise = require('bluebird') const Twitter = require('twitter') const TwitterStream = module.exports = function TwitterStream (config) { // init Twitter Streaming API for OAuth this.stream = new
'use strict'
const Promise = require('bluebird')
const Twitter = require('twitter')
const TwitterStream = module.exports = function TwitterStream (config) {
// init Twitter Streaming API for OAuth
this.stream = new Twitter({
consumer_key: config.get('/twitter/consumerKey'),
consumer_secret: config.get('/twitter/consumerSecret'),
access_token_key: config.get('/twitter/accessTokenKey'),
access_token_secret: config.get('/twitter/accessTokenSecret')
})
.stream('statuses/filter', {
track: config.get('/twitter/track')
})
}
TwitterStream.prototype.receive = function () {
return new Promise((resolve, reject) => {
this.stream.on('data', resolve).on('error', reject)
})
}
TwitterStream.prototype.destroy = function () {
this.stream.destroy()
}
主要问题是当我创建对象时
const stream = new TwitterStream(config)
stream.receive().then((data) => console.log(data))
当我执行时,只读取一个对象。没有其他数据流
TwitterStream.prototype.receive = function () {
return new Promise((resolve, reject) => {
this.stream
.on('data', (data) => resolve(data)
.on('error', (error) => reject(error))
})
}
您需要在
stream.on
函数的回调中返回承诺。现在,调用receive
方法时,它只返回一个承诺,一旦解决,它将返回值或错误。通过使用Rx扩展,它非常简单:
TwitterStream.prototype.receive = function () {
return Rx.Observable.create((observer) => {
this.stream
.on('data', (data) => observer.onNext(data))
.on('error', (err) => observer.onError(err));
});
}
然后
const stream = new TwitterStream(config)
stream.receive().subscribe((data) => console.log(data));
下面是一段未经测试且很可能仍然存在错误的代码,以说明如何通过承诺实现这一点:
function defer() {
var resolve, reject;
var promise = new Promise(function() {
resolve = arguments[0];
reject = arguments[1];
});
return {
resolve: resolve,
reject: reject,
promise: promise
};
}
TwitterStream.prototype.receive = function() {
this.stream
.on('data', data => {
this.dataCache = this.dataCache || [];
this.dataCache.push(data);
this.tryToSendData()
})
.on('end', () => {
this.finished = true;
this.tryToSendData()
})
.on('error', err => {
this.lastError = err;
// error handling still missing
})
return this;
}
TwitterStream.prototype.tryToSendData = function() {
if (this.defered) {
let defered = this.defered;
this.defered = null;
// if data is available or finished then pass the first element of buffer (or undefined)
defered.resolve(this.dataCache.shift())
}
}
TwitterStream.prototype.getNextData = function() {
if (this.dataCache.length > 0 || this.finished) {
// if data is available or finished then pass the first element of buffer (or undefined)
return Promise.resolve(this.dataCache.shift());
} else {
// otherwise we need a defered object
this.defered = defer();
}
}
然后,用法可能如下所示:
stream.receive().getNextData()
.then(function processData(data) {
if (data) {
console.dir(data);
// if data is available then continue requestin the data
return stream.getNextData().then(processData);
}
})
这是一个罕见的情况,你可以使用延迟。我想你可能想看看我的,已经承诺的数据流 对于您的Twitter示例,此代码应该运行良好:
const stream = new Twitter({
consumer_key: config.get('/twitter/consumerKey'),
consumer_secret: config.get('/twitter/consumerSecret'),
access_token_key: config.get('/twitter/accessTokenKey'),
access_token_secret: config.get('/twitter/accessTokenSecret')
})
.stream('statuses/filter', {
track: config.get('/twitter/track')
})
.pipe(new scramjet.DataStream)
然后执行您喜欢的任何转换。。。例如,以某种方式映射流,并在完成后将流累积到一个数组中
stream.map(
function (a) { return modifyTheTweetSomehow(a); } // a Promise can be returned here
).accumulate(
function(a, i) { a.push(i); },
[]
) // this returns a Promise that will be resolved on stream end.
我希望你喜欢 我不知道TwitterStreamAPI。此流是否无限期打开,只要有新数据(tweet)可用,就会发出
数据事件。只有当连接中断时才会调用end
?@t.niese是的,您不能直接将承诺映射到此类流。我将尝试创建一个示例来解决这个问题。您不能对流使用承诺:它们只产生一个值。使用Rx。可观察instead@olivarra1好的,谢谢,正如我预料的那样,那是不可能的,你是说?(编辑了问题)我已经尝试过了,但它不起作用。是的,因为函数在调用时将返回一个承诺。如果没有多次调用该流,则不会多次读取该流。注册事件处理程序将是更好的方法。我的答案本身是错误的,因为我没有正确理解这个问题。我的不好。虽然它看起来是多余的(因为在订阅时您仍然必须传入回调),但它与使用承诺时具有相同的好处:您可以应用map、compose等操作,这非常有用。