我有一段简单的代码,可以使用fs
读取JSON文件。我正在使用回调,并在获得数据后将其用于配置应用程序的另一部分。
如果我不使用超时,或者将事件处理程序放入fs
回调中,则会引发错误。
/**
*
* consumer.js
*
* Subscribes to a kafka topic to consume
* messages sent by our producer.
*
*/
// Defined constants
const kafka = require('kafka-node'),
Consumer = kafka.Consumer,
client = new kafka.KafkaClient(),
utilities = require('./utilities'),
fs = require('fs');
// Defined vars
let consumer = {};
// Load our topics to subscribe to
fs.readFile('./json/topics.json', readTopicFile);
/**
* Handle our file load
* @param {*} err
* @param {*} data
*/
function readTopicFile(err, data) {
// Handle file read error
if (err) {
utilities.logError('Error reading topic file', err);
return;
}
// Define our topic data
let obj = JSON.parse(data);
// Define our consumer
consumer = new Consumer(
client,
obj,
{
autoCommit: false,
fromOffset: 'latest'
}
);
// Start out consumer
setTimeout(function () {
startConsumer();
}, 100);
}
/**
* Wait for messages from our subscribed topics
*/
function startConsumer() {
console.log('consumer waiting for data ...')
consumer.on('message', function (message) {
utilities.storeRecord(message); // Error in this utility function if timeout isn't in place
});
}
对于上下文,这是我的实用程序文件:
storeRecord: function (payload) {
// Define our postgres instance
var pg = require('pg');
var utilities = require('./utilities');
// Connect to the postgres instance
pg.connect(process.env.DATABASE_URL, function (err, conn, done) {
// watch for any connect issues
if (err) {
logError('Unable to connect to postgres', err);
}
// Check to see if we got our payload
if (payload) {
// Holds our payload data
const val = JSON.parse(payload.value).data; // <<<--- Without the setTimeout on the consumer.js, this throws the error.
// Insert the data
const sql = 'INSERT INTO communications (firstname, lastname, age, department, campus, state) VALUES ($1, $2, $3, $4, $5, $6)';
const values = [val.firstName, val.lastName, val.age, val.department, val.campus, val.state];
conn.query(sql, values, (err, result) => {
done();
if (err) {
utilities.logError('Error inserting data into table', err);
} else {
utilities.logError('Inserted data', result);
}
});
}
});
}
在上面的代码中,我的utilities.storeRecord
在期望从message
获取数据的地方抛出错误。
我的问题是关于为什么使用setTimeout
可以解决计时问题。我的实用程序文件引发的错误是TypeError: Cannot read property 'data' of null
。
据我所知,好像new Consumer
没时间初始化并且不知道它正在使用fromOffset: 'latest'
。我认为情况确实如此,因为message
事件中不应包含consumer.on('message', ...
。
如果我登录message
超时,则没有数据通过。如果我在没有超时的情况下登录message
,它将列出主题开头的所有消息(因为它不知道我们只需要最新消息)。
我坚持使用此超时还是有一种更好的方法来初始化Consumer
,以便事件能更快地知道它?