保留流中的上下文

时间:2016-08-22 22:58:35

标签: node.js rxjs

如何预先设置上下文,而不是直接在流中访问?

例如:

我尝试使用简单地将响应映射到结果的流来建模请求/响应。要启用这样的用途:

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)
)

1 个答案:

答案 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!');
  });