简体   繁体   English

将异步转换为Rx.js

[英]convert async to Rx.js

So, we are trying to rewrite our express server into Rx . 因此,我们正在尝试将express服务器重写为Rx It is currently using async for all stream operations. 当前,它对所有流操作都使用async The code looks like the following: 该代码如下所示:

var async = require('async');

function getCountAndChannels(name, cb){
    var tasks = [
        function(cb) {
             //does a mongoDB search and returns count
        },
        function(cb) {
            //does a findOne mongoDB search and returns 
        }
    ];
    async.parallel(tasks, cb);
}

router.get('data', function(req, res) { //router is the express router
    var recorders = req.query.recorders.split(',');

    async.map(recorders, function(name, cb) {
        getCountAndChannels(name, cb);
    }, function(err, countsAndChannels) {
        if(err) throw err;

        // here countsAndChannels is an array with first element the count
        // and second element the document.

        // do other async stuff based on the results

        res.status(200).json('send some calculations');
});

The thing here I have to do is loop over the array of recorders and for each one calculate the two mongoDB searches. 我要做的事情是遍历一系列recorders并为每个recorders计算两个mongoDB搜索。 I have tried using Rx.Observable.merge which doesn't return the results in an array but in 2 different calls of the callback. 我尝试使用Rx.Observable.merge ,它不会在数组中返回结果,而是在回调的2个不同调用中返回结果。 So, then I tried Rx.Observable.zip which I believe is what I'm looking for. 所以,然后我尝试了Rx.Observable.zip ,我相信这是我想要的。

The problem is I don't know how to loop over the recorders and send the result when all operations are finished. 问题是我不知道如何在所有操作完成后遍历recorders并发送结果。 Because a simple forEach loop will throw a Cannot set headers after they are sent error. 因为一个简单的forEach循环将Cannot set headers after they are sent错误Cannot set headers after they are sent引发Cannot set headers after they are sent

This is what I have so far: 这是我到目前为止的内容:

recorders.forEach(recorder => {        
    Rx.Observable.zip([
        search1,
        search2
    ]).subscribe(
        (countsAndChannels) => {                
            // do stuff
            res.send('the results');
        },
        err => res.status(500).json(err),
        () => res.send('OK')
    );  
});

Haven't used Rx before, so any help is appreciated. 以前没有使用过Rx,因此不胜感激。

It might be easier to convert your list of recorders to an Observable stream, then flatMap over each recorder (ie perform your async processing), then call toArray to store all the results into an array: 将记录器列表转换为Observable流,然后在每个记录器上进行flatMap (即执行异步处理),然后调用toArray将所有结果存储到数组中可能会更容易:

var recorder$ = Rx.Observable.from(recorders);
var countsAndChannels$ = recorder$
    .flatMap(performAsyncTask);

// allResults$ will emit once all of the async work is complete
var allResults$= countsAndChannels$.toArray();

allResults$.subscribe(results => {
    // Send response to client;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM