问候伙计。
你能帮我解决 node.js 中的异步问题吗?
问题:
我使用amqplib module与RabbitMQ合作,此处有方法消费,他从RabbitMQ发出消息,但该方法首先返回承诺关于他开始并且在这个承诺开始之后,他从RabbitMQ调用回调来获取数据,并且我不知道当所有消息将被发送到我的节点js app时如何捕获。
更多解释,这里我的代码和评论的结束代码我写了我想要的东西:
/**
* Here my test code
*
* requirng amqp.node lib
*/
let amqp = require('amqplib')
, configConnection = { /* ..config options */ }
, queue = 'users'
, exchange = 'users.exchange'
, type = 'fanout'
/**
* declare annonymous function as async and immediately called it
*/
(async () => {
/**
* declare connection and channel with using async/await construction
* who support version node.js >= 8.5.0
*/
let conn = await amqp.connect(configConnection)
let channel = await conn.createChannel()
await channel.assertExchange(exchange, type)
let response = await channel.assertQueue(queue)
/**
* response: { queue: 'users', messageCount: 10, consumerCount: 0 }
*/
response = await channel.bindQueue(response.queue, exchange, '')
response = await channel.consume(response.queue, logMessage, {noAck: false})
/**
* {noAck: false} false for not expect an acknowledgement
*/
console.log('reading for query finish')
function logMessage(msg) {
console.log("[*] recieved: '%s'", msg.content.toString())
}
})()
/**
* output will show:
* reading for query finish
* [*] recieved: 'message content'
* [*] recieved: 'message content'
* [*] recieved: 'message content'
* ...
*
* But i'm need show message 'reading for query finish' after when
* all consumes will executed
*
* Ask: How i can do this?
*/
答案 0 :(得分:1)
我在问题here上找到了答案。
使用中的答案:EventEmitter&&承诺
魔法(对我来说)就在这里:await new Promise(resolve => eventEmitter.once('consumeDone', resolve))
所以结束的代码是:
/**
* Here my test code
*
* requirng amqp.node lib
*/
let amqp = require('amqplib')
, EventEmitter = require('events')
, eventEmitter = new EventEmitter()
, timeout = 10000
, configConnection = { /* ..config options */ }
, queue = 'users'
, exchange = 'users.exchange'
, type = 'fanout'
/**
* declare annonymous function as async and immediately called it
*/
(async () => {
/**
* declare connection and channel with using async/await construction
* who support version node.js >= 8.5.0
*/
let conn = await amqp.connect(configConnection)
let channel = await conn.createChannel()
await channel.assertExchange(exchange, type)
let response = await channel.assertQueue(queue)
/**
* response: { queue: 'users', messageCount: 10, consumerCount: 0 }
*/
let messageCount = response.messageCount
response = await channel.bindQueue(response.queue, exchange, '')
response = await channel.consume(response.queue, logMessage(messageCount), {noAck: false})
/**
* {noAck: false} false for not expect an acknowledgement
*/
/**
* declare timeout if we have problems with emit event in consume
* we waiting when event will be emit once 'consumeDone' and promise gain resolve
* so we can go to the next step
*/
setTimeout(() => eventEmitter.emit('consumeDone'), timeout)
await new Promise(resolve => eventEmitter.once('consumeDone', resolve))
console.log('reading for query finish')
function logMessage(messageCount) {
return msg => {
console.log("[*] recieved: '%s'", msg.content.toString())
if (messageCount == msg.fields.deliveryTag) {
eventEmitter.emit('consumeDone')
}
}
}
})()
答案 1 :(得分:0)
尝试以下代码:
let amqp = require('amqplib/callback_api');
function init() {
let configConnection = {
protocol: 'amqp',
hostname: 'localhost',
port: 5672,
username: 'root',
password: '1111',
heartbeat: 60,
};
let messageCount = 0;
let messageCounter = 0;
let queue_name = 'queue_name';
let messages = [];
amqp.connect(configConnection, function (error, connect) {
if (error) {
throw error;
}
// Create channel and get info about queue
connect.createChannel(function (error1, channel) {
if (error1) {
throw error1;
}
channel.assertQueue(queue_name, {durable: true}, (error2, result) => {
// here you get count of messages
messageCount = result.messageCount;
// Consume to queue
channel.consume(queue_name, function (msg) {
msg = msg.content.toString();
messages.push(msg);
// Show all messages and exit
if (messageCount === ++messageCounter) {
console.log(messages);
process.exit();
}
}, {
noAck: true
});
});
});
});
}
init();