NodeJS:无法发出事件“Object ... {}没有方法'emit'

时间:2014-08-17 20:37:19

标签: node.js express cql

我遵循了一些Nodejs教程,通过一个简单的REST Web服务。此webservices侦听/ api / accounts以查找电子邮件和密码,然后继续在Cassandra集群中进行查找。 我使用EventEmitter来避免回调地狱。一切正常,直到尝试发射('成功'):

events.js:72
        throw er; // Unhandled 'error' event
              ^
TypeError: Object SELECT * FROM accounts WHERE email_accounts=?,test@gmail.com,77ddcc8d868e1532f86f0e25f35d43e5,function _checkPassword(error, response) {
        var rows=response.rows;
        if (_checkForErrors(error, rows , 'password')) {
            return false;
        } else {
            if ( rows.length == 1 ) {
                console.log('got user profile with password_accounts ' + rows[0].pwd_accounts);
                this.emit('success', rows[0] );
            }
        }
    } has no method 'emit'
    at Array._checkPassword (/home/scoulibaly/node/login.js:33:10)
    at /home/scoulibaly/node/node_modules/node-cassandra-cql/index.js:220:16
    at Connection.handleResult (/home/scoulibaly/node/node_modules/node-cassandra-cql/lib/connection.js:308:3)
    at ResultEmitter.EventEmitter.emit (events.js:106:17)
    at ResultEmitter.bufferAndEmit (/home/scoulibaly/node/node_modules/node-cassandra-cql/lib/streams.js:456:10)
    at ResultEmitter.each (/home/scoulibaly/node/node_modules/node-cassandra-cql/lib/streams.js:440:17)
    at ResultEmitter._write (/home/scoulibaly/node/node_modules/node-cassandra-cql/lib/streams.js:413:10)
    at doWrite (_stream_writable.js:223:10)
    at writeOrBuffer (_stream_writable.js:213:5)
    at ResultEmitter.Writable.write (_stream_writable.js:180:11)

我的主要是server.js。我使用Express和router()来设置路由:

// server.js

// BASE SETUP
// =============================================================================

// call the packages we need
var express    = require('express');        // call express
var app        = express();                 // define our app using express
var bodyParser = require('body-parser');


var Login   = require('./login');

// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var port = process.env.PORT || 8080;        // set our port

// ROUTES FOR OUR API
// =============================================================================
var router = express.Router();              // get an instance of the express Router

// middleware to use for all requests
router.use(function(req, res, next) {
    // do logging
    console.log('Something is happening.');
    next(); // make sure we go to the next routes and don't stop here
});


router.route('/accounts')
    // get the account with that id (accessed at GET http://localhost:8080/api/accounts/:account_id)
    .get(function(req, res) {
       var login = new Login(req.query.email, req.query.password);
        login.on('error', function (error) {
            res.writeHead(500);
            res.end();
        });
        login.on('failure', function (reason) {
            if (reason == 'email') {
                res.end('Wrong email!');
            } else if (reason == 'password') {
                res.end('Wrong password!');
            }
        });
        login.on('success', function (data) {
            res.json(data);
        });
        login.perform();
    });


// test route to make sure everything is working (accessed at GET http://localhost:8080/api)
router.get('/', function(req, res) {
    res.json({ message: 'hooray! welcome to our api!' });   
});

// more routes for our API will happen here

// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', router);

// START THE SERVER
// =============================================================================
app.listen(port);
console.log('Magic happens on port ' + port);

我的login.js扩展了EventEmitter:

// login.js

var util        = require('util');
var eventEmitter = require('events').EventEmitter;
var cql        = require('node-cassandra-cql');


function Login(email,password) {
    // Error checking
    function _checkForErrors(error, rows, reason) {
        if (error) {
            console.log('emit err');
            this.emit('error', error);
            return true;
        }

        if (rows.length < 1) {
                        console.log('emit fail');
            this.emit('failure', reason);
            return true;
        }

        return false;
    }

    // Check {email,pwd}
    function _checkPassword(error, response) {
        var rows=response.rows;
        if (_checkForErrors(error, rows , 'password')) {
            return false;
        } else {
            if ( rows.length == 1 ) {
                console.log('got user profile with password_accounts ' + rows[0].pwd_accounts);
                this.emit('success', rows[0] );
            }
        }
    }

    function perform() {
        var client = new cql.Client({hosts: ['localhost', 'localhost'], keyspace: 'node'});
        client.execute('SELECT * FROM accounts WHERE email_accounts=?', [ email , password ], _checkPassword );
    }

    this.perform = perform;
} 

util.inherits(Login, eventEmitter);
module.exports = Login;

看起来像这个&#39;在this.emit()行中引用CQL对象。根据我的理解,只要数据准备就绪,cql驱动程序就会调用回调,因此&#39;这个&#39; object不再是Login对象。我错了吗 ?如何使emit()正常工作?

谢谢

1 个答案:

答案 0 :(得分:2)

在Login对象定义的顶部附近,通过以下方式创建this的句柄:

var _this = this;

在调用_this方法时,请使用this代替emit。据说_checkPassword 关闭超过_this(它不能超过this)。

this关键字是一个特殊的雪花,在调用封闭函数时会动态绑定;如果您将引用this的函数传递给其他函数,请确保this符合您的想法。 :)