我有一个在Raspberry Pi上运行的node.js ES6项目,该项目带有一个主文件和一些导入的ES6子模块(示例中为http和一个温度传感器)。
当服务器收到请求时,我想调用一个异步父函数(我可以使用EventEmitter做到这一点),并在页面上回调打印温度值。
我可以这样做吗? 问题是响应没有关闭(因此客户端页面永远不会结束),如果我重复调用,它会告诉我服务器:port已经很忙。
简短摘要
...
self.webserver.on('request', async (req, res) => {
...
self.emit('remoteCall', path, JSON.stringify(queryData)); // call parent
self.on('callback',(data)=>{ // <-- HERE callback from index.js with temperature data collected
res.write(data);
res.end(); // <-- I want to wait for temperature data and then end server response
});
});
...
完整示例
/**
* ./app/services/server/server.js Server module
*/
const http = require('http');
const url = require('url');
const EventEmitter = require( 'events' );
class Server extends EventEmitter {
constructor(){
super();
this.webserver = http.createServer();
this.remoteServer = 'https://example.com/';
}
startServer(){
const self = this;
self.webserver.on('request', async (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
const q = url.parse(req.url, true);
if (q.pathname === '/favicon.ico') {
res.writeHead(200, {'Content-Type': 'image/x-icon'} );
res.end();
return;
}
const path = q.pathname;
const queryData = q.query;
res.write(path);
res.write(JSON.stringify(queryData));
self.emit('remoteCall', path, JSON.stringify(queryData)); // <-- send to index.js so it can execute temperature read
self.on('callback',(data)=>{ // <-- HERE callback from index.js with temperature data collected
console.log(data);
res.write(data);
res.end(); // <-- I want to wait for temperature data and then end server response
});
});
}
listen(){
this.webserver.listen(8080);
return
}
}
export default Server;
/**
* ./app/probes/tempereture/tempereture.js Temperature module
*/
const sensor = require('ds18x20');
class Temperature {
constructor(id) {
this.id = id;
}
async getTemperature() {
const self = this;
return new Promise(resolve => {
sensor.get(self.id, function (err, tempObj) {
if (err) { throw err; }
resolve({id: self.id, value: tempObj});
});
});
}
}
export default Temperature;
/**
* ./app/evoirement/pot/pot.js Temperature object parent
*/
import Temperature from '../../probes/temperature/temperature';
class Pot {
constructor({potID, waterTemperatureProbeID}) {
this.id = potID;
this.waterTemperature = new Temperature(waterTemperatureProbeID);
}
}
export default Pot;
/**
* index.js Main file
*/
import Pot from './app/envoirement/pot/pot';
import Server from './app/services/server/server';
class Main {
constructor(){
this.server = new Server();
this.appSetup();
}
appSetup(){
const self = this;
this.pot1 = new Pot({
potID: 'pot1',
waterTemperatureProbeID: '28-0114502296aa'
});
this.pot2 = new Pot({
potID: 'pot2',
waterTemperatureProbeID: '28-0114504ea1aa'
});
this.server.startServer();
this.server.listen();
this.server.on('remoteCall', (path, queryData) => { // <-- Received a request from http server
console.log('remoteCall', path, queryData);
self.pot1.waterTemperature.getTemperature().then(res=>{
console.log(res);
this.server.emit('callback', res)
});
});
}
}
const app = new Main();
答案 0 :(得分:0)
您不想这样做,因为远程调用是针对服务器的-这意味着所有并发连接。您应该做的是根据请求而不是按服务器进行远程调用。
只需在您的请求处理程序中直接调用getTemperature()
:
import Pot from './app/envoirement/pot/pot';
let pot1 = new Pot({
potID: 'pot1',
waterTemperatureProbeID: '28-0114502296aa'
});
class Server {
constructor(){/* ... */}
startServer(){
const self = this;
self.webserver.on('request', async (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
const q = url.parse(req.url, true);
if (q.pathname === '/favicon.ico') {
res.writeHead(200, {'Content-Type': 'image/x-icon'} );
res.end();
return;
}
const path = q.pathname;
const queryData = q.query;
res.write(path);
res.write(JSON.stringify(queryData));
pot1.waterTemperature.getTemperature().then(data=>{
console.log(data);
res.write(data);
res.end();
});
});
}
listen(){/* ... */}
}
如果您不想在Server中对pot1
进行硬编码,则将其作为参数传递给构造函数-一种轻量级的依赖注入:
class Server {
constructor(pot1){
this.pot1 = pot1;
// ...
}
startServer(){/* ... */}
listen(){/* ... */}
}
如果要排除传感器以使其模块化,可以将其保留在自己的模块中:
// sensors.js
let pot1 = new Pot({
potID: 'pot1',
waterTemperatureProbeID: '28-0114502296aa'
});
let pot2 = new Pot({
potID: 'pot2',
waterTemperatureProbeID: '28-0114504ea1aa'
});
module.exports = {
pots: [
pot1, // the namespacing of this API is really up to you
pot2
]
}
然后您可以将其导入服务器中:
let sensors = require('./sensors');
class Server {
constructor(){/* ... */}
startServer(){
const self = this;
self.webserver.on('request', async (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
const q = url.parse(req.url, true);
if (q.pathname === '/favicon.ico') {
res.writeHead(200, {'Content-Type': 'image/x-icon'} );
res.end();
return;
}
const path = q.pathname;
const queryData = q.query;
res.write(path);
res.write(JSON.stringify(queryData));
sensors.pot[1].waterTemperature.getTemperature().then(data=>{
console.log(data);
res.write(data);
res.end();
});
});
}
listen(){/* ... */}
}
然后您可以动态查询传感器:
self.webserver.on('request', async (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
const q = url.parse(req.url, true);
if (q.pathname === '/favicon.ico') {
res.writeHead(200, {'Content-Type': 'image/x-icon'} );
res.end();
return;
}
const path = q.pathname;
const queryData = q.query;
const query = queryData.split('&').reduce(function(a,b){
keyVal = b.split('=');
a[keyVal[0]] = keyVal[1];
},{});
res.write(path);
res.write(JSON.stringify(queryData));
sensors.[query.type][query.idx].waterTemperature.getTemperature()
.then(data=>{
console.log(data);
res.write(data);
res.end();
});
});
现在,您可以发出类似http://server/get?type=pot&idx=0
的请求。同样,如果您不想硬编码将传感器导入服务器文件中,则可以始终将其作为参数传递给构造函数。