第一次请求后事件发射器无法正常工作
Event emitter doesn't work properly after first request
我的 express.js 应用程序中有一个基本控制器。我尝试执行某项服务,在稍有延迟后获取模拟数据。该服务继承自EventEmitter,接收到数据后发出SUCCESS
事件
这是我的控制器:
const express = require('express');
const router = express.Router();
const GetAllUsers = require('../GetAllUsers');
const getAllUsers = new GetAllUsers();
router.get('/', function(req, res, next) {
getAllUsers
.on('SUCCESS', (users) => {
res
.status(200)
.json({ users });
})
.on('ERROR', next);
getAllUsers.execute();
});
module.exports = router;
和服务:
const EventEmitter = require('events');
class GetAllUsers extends EventEmitter {
async execute() {
const data = [{ id: 1, name: 'user 1' }, { id: 2, name: 'user 2' }];
try {
const users = await new Promise(resolve => {
setTimeout(() => {
resolve(data);
}, 1000);
})
this.emit('SUCCESS', users);
} catch (error) {
this.emit('ERROR', error);
}
}
}
module.exports = GetAllUsers;
问题是,当我第一次进入 /users
路径时,我实际上得到了一个用户列表。但是当我第二次及以后尝试时,出现以下错误:
Cannot set headers after they are sent to the client
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:471:11)
at ServerResponse.header (/home/debian/dev/sandbox/emitterTest/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/home/debian/dev/sandbox/emitterTest/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/home/debian/dev/sandbox/emitterTest/node_modules/express/lib/response.js:267:15)
at GetAllUsers.getAllUsers.on (/home/debian/dev/sandbox/emitterTest/routes/users.js:12:10)
at GetAllUsers.emit (events.js:187:15)
at GetAllUsers.execute (/home/debian/dev/sandbox/emitterTest/GetAllUsers.js:14:12)
据我了解,headers 在我发送回复之前设置在某处。
当我尝试在没有发射器的情况下实现我的控制器时,一切正常:
router.get('/', async function(req, res, next) {
const data = [{ id: 1, name: 'user 1' }, { id: 2, name: 'user 2' }];
const users = await new Promise(resolve => {
setTimeout(() => {
resolve(data);
}, 1000);
})
res
.status(200)
.json({ users });
});
如何解决这个问题?
发生这种情况是因为每次发出请求时,您 运行 您的路由器功能:
function(req, res, next) {
getAllUsers
.on('SUCCESS', (users) => { //subscribe to event every time
res
.status(200)
.json({ users });
})
.on('ERROR', next);
getAllUsers.execute();
}
您已经订阅了这些活动并且 运行 订阅了一次。当时,您发出了第二个请求,您有 2 个订阅者:来自上一个请求和当前请求。然后,execute()
函数触发事件。因此一次执行了 2 个函数,其中一个 尝试再次发送响应,但这是不可能的,因此会导致错误。
如果确实需要这些事件发射器,您可以使用getAllUsers.once
函数只订阅一次触发事件。
我的 express.js 应用程序中有一个基本控制器。我尝试执行某项服务,在稍有延迟后获取模拟数据。该服务继承自EventEmitter,接收到数据后发出SUCCESS
事件
这是我的控制器:
const express = require('express');
const router = express.Router();
const GetAllUsers = require('../GetAllUsers');
const getAllUsers = new GetAllUsers();
router.get('/', function(req, res, next) {
getAllUsers
.on('SUCCESS', (users) => {
res
.status(200)
.json({ users });
})
.on('ERROR', next);
getAllUsers.execute();
});
module.exports = router;
和服务:
const EventEmitter = require('events');
class GetAllUsers extends EventEmitter {
async execute() {
const data = [{ id: 1, name: 'user 1' }, { id: 2, name: 'user 2' }];
try {
const users = await new Promise(resolve => {
setTimeout(() => {
resolve(data);
}, 1000);
})
this.emit('SUCCESS', users);
} catch (error) {
this.emit('ERROR', error);
}
}
}
module.exports = GetAllUsers;
问题是,当我第一次进入 /users
路径时,我实际上得到了一个用户列表。但是当我第二次及以后尝试时,出现以下错误:
Cannot set headers after they are sent to the client
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:471:11)
at ServerResponse.header (/home/debian/dev/sandbox/emitterTest/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/home/debian/dev/sandbox/emitterTest/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/home/debian/dev/sandbox/emitterTest/node_modules/express/lib/response.js:267:15)
at GetAllUsers.getAllUsers.on (/home/debian/dev/sandbox/emitterTest/routes/users.js:12:10)
at GetAllUsers.emit (events.js:187:15)
at GetAllUsers.execute (/home/debian/dev/sandbox/emitterTest/GetAllUsers.js:14:12)
据我了解,headers 在我发送回复之前设置在某处。
当我尝试在没有发射器的情况下实现我的控制器时,一切正常:
router.get('/', async function(req, res, next) {
const data = [{ id: 1, name: 'user 1' }, { id: 2, name: 'user 2' }];
const users = await new Promise(resolve => {
setTimeout(() => {
resolve(data);
}, 1000);
})
res
.status(200)
.json({ users });
});
如何解决这个问题?
发生这种情况是因为每次发出请求时,您 运行 您的路由器功能:
function(req, res, next) {
getAllUsers
.on('SUCCESS', (users) => { //subscribe to event every time
res
.status(200)
.json({ users });
})
.on('ERROR', next);
getAllUsers.execute();
}
您已经订阅了这些活动并且 运行 订阅了一次。当时,您发出了第二个请求,您有 2 个订阅者:来自上一个请求和当前请求。然后,execute()
函数触发事件。因此一次执行了 2 个函数,其中一个 尝试再次发送响应,但这是不可能的,因此会导致错误。
如果确实需要这些事件发射器,您可以使用getAllUsers.once
函数只订阅一次触发事件。