如何首先发出然后回调?

时间:2015-07-12 14:40:11

标签: javascript node.js

我不能让发射器在回叫之前发出从pg模块返回的信号。这是我的情况。

questionHandler_upqid.js:

var express = require('express');
var router = express.Router();
var pg = require('pg');
var connectionString = process.env.DATABASE_URL || 'postgres://admin:admin@localhost:5432/mydb'; 

var question_id;
var resource_id = [];
//var err_ = [];    //Move to local function
var mcres = [];
exports.addResourceFile = function(req, res, err, client, done, callback){
    var cb_is_func = (typeof(callback)==='function');
    console.log('addResourceFile function called');
    var err_ = [];
    var resourcefiles = req.body.resourcefiles;
    var idx = 0;
    //Use local function because of err + client + done scope.
    exports.addResourceFile_inside = function (element, index, array){
        console.log('addResourceFile_inside function called, index : ' + index);
        var func_ = 'SELECT Dugong.resourcefile_Add($1,$2,$3)';
        //rfdata = resource file data.  
        var rfdata = [element.fileurl,
                                 element.name,
                                 element.type];
        console.log(rfdata);        

        var addResourceFile_ = client.query(func_, rfdata);

        //Add underscore (_) to prevent confusion.
        addResourceFile_.on('error', function(err){
            console.log('error signal from addResourceFile');
            var tempdata = {success : false, 
                                        id : -1,
                                        reason : {errmsg : err.detail,
                                                            errid : 'addResourceFile' + index }};   //plus index to spot record
            err_.push(tempdata);
        });

        addResourceFile_.on('row', function(row){
            console.log('row signal from addResourceFile_');
            resource_id.push(row.resourcefile_add);
        });

        console.log('hello world');
        callback(err_, resource_id);
        return ;


    };

/*
    //Want sequential run of these.
    //But it does not.
    resourcefiles.forEach(exports.addResourceFile_inside);
    callback(err_, resource_id);
    return ;
*/

//Emitter emits lastest. callback executed first.
    exports.action = function(){
        resourcefiles.forEach(exports.addResourceFile_inside);
    };
    exports.summary = function(){
        callback(err_, resource_id);
    };

    exports.summary(
        exports.action()
    );


};

我的单元测试: questionHandler_upqid.js

  var httpMocks = require('node-mocks-http');
    var test = require('unit.js');

    var real_questionHandler = require('../routes/questionHandler_upqid.js');

    var proxyquire =  require('proxyquire'),
        pgStub   =  { };

    var events = require('events');

    describe('questionHandler_upqid : ', function () {
        var request;
        beforeEach(function (){
        request  = httpMocks.createRequest({
            method: 'PUT',
              url: '/questions',
            params: {id : 1 },
            body : { questiontype : 'Multiple Choice', 
                             problemtext : 'Find x when x is 4 + 2',
                             excerpttext : 'Somewhere I belong',
                             solutiontext : '6',    
                             authorid: 'Sarit1',
                             subjectid: '2',
                             lastmod: '2099-0101 00:00:02',
                             resourcefiles : [{"name":"penguin","type":"jpeg","fileurl":"/1.jpeg"},
                                                                {"name":"penguin","type":"jpeg","fileurl":"/2.jpeg"},
                                                                {"name":"penguin","type":"jpeg","fileurl":"/3.jpeg"},
                                                                {"name":"penguin","type":"jpeg","fileurl":"/4.jpeg"},
                                                                {"name":"penguin","type":"jpeg","fileurl":"/5.jpeg"}],
                            mcresponses : [{"text":"BX","image":"A1","iscorrect":false},
                                                            {"text":"BW","image":"A2","iscorrect":false},
                                                            {"text":"ACRA","image":"A3","iscorrect":true},
                                                            {"text":"GxM","image":"A4","iscorrect":false}]  
                                                            //Do not change lenght of mcresponse.
                                                            //mcres_length is used in 'should add MCResponse with error'
                }
        });
        pgStub.end = function(){};
        });
    it('should add ressource file with error', function(done){
        //emitter emit 'error'
        var client = {};
        client.query = function(querystr, data){
            var emitter = new events.EventEmitter();
                setTimeout(function(){
                    console.log('emit diode add resource file with error');
                    error = {detail : 'Resrc file can be changed!'};
                    emitter.emit('error', error);
                },0);
                console.log('add emitters');
                return emitter;
        };
        var response = httpMocks.createResponse();
        var questionHandler_upqid = proxyquire('../routes/questionHandler_upqid.js', { 'pg' : pgStub} );
        questionHandler_upqid.addResourceFile(request, response, null, client, null, function(err, resrc_id){
            console.log(err);
            console.log(resrc_id);
            done();
        });         

    });

});

此代码在调用回调后仍会发出。

var p1 = new Promise(function(){
resourcefiles.forEach(exports.addResourceFile_inside);
}); 
p1.then(callback(err_, resource_id));

我有2个空白的err_和resource_id数组。然后拿出来自发射器的信号。实际上我希望先执行发射器然后再回调。回调应该返回2个数组。它们是err_和resource_id。

2 个答案:

答案 0 :(得分:0)

您需要将回调绑定到其中一个pg的事件,以便在调用之前知道查询已完成。

'row''error'事件一起,其Query个对象也会发出'end' event when all rows have been received successfully

addResourceFile_.on('row', function(row){
    console.log('row signal from addResourceFile_');
    resource_id.push(row.resourcefile_add);
});

addResourceFile_.on('end', function () {
    callback(null, resource_id);
});

但是,如果存在错误,则不会发出'end'事件(因此您可以安全地假设为null),因此您需要从callback调用'error' {1}}事件也包括成功和失败:

addResourceFile_.on('error', function (err) {
    console.log('error signal from addResourceFile');
    var tempdata = {
        success : false,
        id : -1,
        reason : {
            errmsg : err.detail,
            errid : 'addResourceFile' + index // plus index to spot record
        }
    };
    callback(tempdata, null);
});

答案 1 :(得分:0)

我不知道这是一个好的编码风格,但仅仅是暂时的。我顺便去了。

addResourceFile_.on('error', function(err){
    console.log('error signal from addResourceFile');
    var tempdata = {success : false, 
                                id : -1,
                                reason : {errmsg : err.detail,
                                                    errid : 'addResourceFile' + index }};   //plus index to spot record
    err_.push(tempdata);
    console.log(idx);
    if(idx === array.length - 1){
        callback(err_, resource_id);
    }
    idx = idx + 1;
});

addResourceFile_.on('row', function(row){
    console.log('row signal from addResourceFile_');
    resource_id.push(row.resourcefile_add);
    if(idx === array.length - 1){
        callback(err_, resource_id);
    }   
    idx = idx + 1;
});