如何预先设置上下文,而不是直接在流中访问?
例如:
我尝试使用简单地将响应映射到结果的流来建模请求/响应。要启用这样的用途:
requests
.filter(req => req.url == '/')
.map(req => {body: 'Hello, World!'})
requests
.filter(req => req.url == '/etc')
.map(req => {body: 'etc.'})
我遇到的问题是Node.js的http
模块有这样的界面:
server.on('request', (request, response) => ...)
所以我会得到一个request
对象,我可以在Observable
中使用,但response
对象是请求上下文的一部分,所以我将请求映射到的数据需要导致相应的response
对象。
这只会创建一个请求流:
const requests = new Observable(o =>
server.on('request', r => o.next(r))
)
我可以将请求数据映射到我喜欢的任何内容。
但是当我订阅结果数据时,如何将其恢复到正确的响应?
我可以以某种方式为请求/响应创建“私有”流,“公开”从中映射响应对象以获取仅请求流,然后将此流的结果映射回原始流吗?
这样的事情:
const private = new Observable(o =>
server.on('request', (request, response) => o.next({request, response})
)
const public = private.map(({request}) => request)
...
public.filter(r => r.url == '/').map(() => {body: 'Hello, World!'})
...
private
.matchUpWith(public)
.((privateData, publicData) =>
privateData.response.end(publicData.body)
)
答案 0 :(得分:1)
如果认为仅使用private
流订阅您的public
流即可实现您的目标。
const private$ = Rx.Observable.of(1,2,3,4,5);
const public$ = Rx.Subject.create({},private$);
public$.subscribe(i => console.log(i));
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.11/dist/global/Rx.umd.js"></script>
使用两个流进行另一次尝试:
const res = {
send: (msg) => { console.log(msg); }
};
const one = { req: { url: '/', data: 'one' }, res };
const two = { req: { url: '/etc', data: 'two' }, res };
const three = { req: { url: '/', data: 'three' }, res };
const private$ = Rx.Observable.of(one,two, three)
.concatMap(({req, res }) => {
// public
return Rx.Observable.of(req)
.filter(r => r.url === '/')
.map(r => ({body: `Hello, ${r.data}!`}))
.map(p => ({ privateData: res, publicData:p }));
})
.subscribe(({privateData, publicData}) => {
privateData.send(publicData.body);
});
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.11/dist/global/Rx.umd.js"></script>
编辑:没有真正理解你的问题。但我在这里留下我的初步答案:
如果我理解正确,您希望通过使用RxJS来处理传入请求来创建“被动”服务器。这应该是一个很好的起点:
import * as Rx from 'rxjs';
import * as http from 'http';
const request$ = new Subject();
const server = http
.createServer((req, res) => request$.next({ req, res }))
.listen(3000);
然后您可以subscribe
/ filter
/ ...使用RxJS的请求:
request$
.filter(req => req.url == '/')
.subscribe(({ res }) => {
res.writeHead(200, {"Content-Type": "text/html"});
res.end('Hello, World!');
});