节点eventAsmitter使用和范围在async.waterfall调用中

时间:2014-02-12 04:36:33

标签: javascript node.js events asynchronous

我正在尝试在节点中编写一个首先解析json stirng的应用程序,验证该字符串是否包含所需的键/值对,并最终对该数据进行更多处理。我们使用async.waterfall来调用我们的函数,因为结果需要从一个函数传递到下一个函数。

我一直在遇到的问题是我相信的范围。作为瀑布的最终回调的一部分,我想发出“错误”或“成功”消息,但无论我做什么,我似乎无法捕获该消息。我文件的重要部分如下所示:

var MetadataIngester = function() {
    var status, returnValue;
    eventEmitter.call(this);
}

util.inherits(MetadataIngester, eventEmitter);

MetadataIngester.prototype.sendEvent = function(eventType, eventMessage) {
    this.emit(eventType, eventMessage);
}

MetadataIngester.prototype.clobber = function(itemString) {
    var self = this;
    var asyncParseItem = self.parseItem;
    var asyncValidateItem = self.validateItem;
    var asyncSendvent = self.sendEvent;
    async.waterfall(
        [
            function(callback) {
                asyncParseItem(itemString, callback);
            },
           asyncValidateItem
        ],
        function(err, result) {
            if (err) {
                asyncSendEvent.call(self, 'wtf', result);
            } else {
                asyncSendEvent.call(self, 'success', {
                    'remedia_id': 123
                });
            }
        }
    );

为了测试这个,我正在做以下事情:

describe("#clobber", function() {
    it('should emit an error event if item has not been inserted', function() {
        item = "{}";
        metadata.on('wtf', errorSpy);
        metadata.clobber(item);
        expect(errorSpy).to.have.been.called;
    });


});

describe("#sendEvent", function() {
     it('should emit an wtf event if an error event type is passed in', function() {
         metadata.on('wtf', errorSpy);
         metadata.sendEvent('wtf', {'ihateyou': 'wtf'});
         expect(errorSpy).to.have.been.called;
     });
});

当我运行第一个测试时,会发出事件,但是从不调用间谍。但是,如果我调用直接发出事件的函数,就像第二次测试的情况一样,它工作正常,我不知道为什么。我需要获取测试文件捕获的事件,因为最终我将使用这个MetadataIngester,其队列将消息从队列中拉出来,而消费者调用此文件并期望返回事件,以便它知道下一步该做什么。 / p>

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

如果您想将范围保留在回调中,请使用Function.bind。这样可以减少代码的混乱(没有魔法selfthat等):

async.waterfall([
    function(callback) {
        this.parseItem(itemString, callback);
    }.bind(this),
    this.validateItem
], function(err, result) {
    if (err) {
        this.endEvent('wtf', result);
    } else {
        this.sendEvent('success', {
            'remedia_id': 123
        }.bind(this));
    }
}.bind(this));