将Observable实现为持久性队列库

时间:2016-12-16 05:15:14

标签: javascript node.js rxjs observable

目前正在编写一个小的持久性队列库,它将读/写行文本文件。这是add方法,例如:

Queue.prototype.add = function(line, cb){

    getLock(this, err => {
        if(err){
            this.emit('error', err);
            releaseLock(err, cb);
        }
        else{
            fs.appendFile(this.filepath, line, err => {
               err && this.emit('error', err);
               releaseLock(err, cb);
            });
        }
    });
};

我觉得很尴尬,支持事件发射器和回调(或事件发射器和承诺)。

换句话说,对于队列中的每个方法(add,peek,remove),我需要返回/回调特定于每个调用的结果。仅使用事件发射器意味着调用者可能对不是特定于他们刚刚进行的调用的结果起作用。所以回调或承诺似乎势在必行 - 你不能只使用事件发射器。

我想知道的是 - 可观察能否以某种方式解决必须将回调与事件发射器或事件发射器的承诺配对的问题?

我希望找到一种方法来实现这个只有一种类型的异步回调机制的事件/异步队列。也许观察不到这里的答案,但我仍在寻找一个好的设计模式。

1 个答案:

答案 0 :(得分:2)

我不太清楚你为什么需要事件发射器......如果你使用observables,每个用户都会从他们自己的电话中获得结果/错误。

我会这样重写你的方法:

function appendFileObs(filePath, line){
    return Rx.Observable.create((obs) => {
        fs.appendFile(filePath, line, (err, result) => {
            if(err) obs.onError(err);
            else {
                obs.onNext(result);
                obs.onCompleted();
            }
        });
    });
});
// Similar for getLock and releaseLock


Queue.prototype.add = function(line){
    return getLockObs(this)
        .flatMap(() => appendFileObs(this.filePath, line))
        .flatMap(result => releaseLockObs(undefined).map(() => result))
        .catch((err) => {
            return releaseLockObs(err);
        });
};

在这个解决方案中,我并不自豪流内部有副作用,它可能是可以改进的,但你明白了。

这样,当有人调用.add(line).subscribe()时,它会得到结果和他调用时发生的错误。

如果您需要广播发生的错误,您可以使用BehaviourSubject,它是一个观察者并同时可观察(有用的东西!)