我正在制作一个anroid应用程序并使用express for backend。 这是我的送货男孩架构:
var DeliveryBoySchema = new Schema({
name: String,
college: {type:String},
password: {type: String, required: true, select: false},
lat:{type: String},
long:{type:String}
});
当送货员改变它的位置时,它会在mongodb中更新。 因此,正在查看此送货员的用户即正在跟踪其位置的用户。我找到了两种方法:
1 。客户端每隔5秒调用一次api并获取送货员的当前位置。
2 。我发现了另一个有趣的方法,即使用套接字。
我对它的功能不太清楚。我在如何在数据库发生更改并且用户看到当前位置时更新客户端时遇到问题。
答案 0 :(得分:4)
仅使用mongoose
,nodeJS
和socket
从OP请求的某些编码。实际实施不必完全相同,但以下内容应提供有关如何继续并填补缺失空白的一般概念。为方便起见,我将仅使用ES6功能。
nodeJS版本 4.2.2 ,socket.io 1.3.5 ,mongoose版本 4.1.2 ,快递 4.13.3 强>
//the following is probably your app.js
import express from 'express'
...
var app = express();
var server = http.createServer(app);
...
var socketio = require('socket.io')(server, {
path: '/socket.io-path, //modify this as per your needs
});
//now register created socket object
require('./components/socket')(socketio);
...
//start the server
//the following is components/socket/index.js
function onConnect(socket){
//register listeners on mongo schema changes
require('../../models/deliveryBoy.socket').register(socket);
}
module.exports = function(socketio){
socketio.on('connection', function(socket) {
socket.address = socket.request.connection.remoteAddress +
':' + socket.request.connection.remotePort;
//address, e.g. 127.0.0.1:52243
socket.connectedAt = new Date();
socket.log = function(...data) {
console.log(`SocketIO ${socket.address}`, ...data);
};
// Call onDisconnect.
socket.on('disconnect', function() {
socket.log('Disconnected: ');
//do something when user disconnects
});
// Call onConnect.
onConnect(socket);
socket.log('New connection: ');
});
};
//this is to be stored at ./models/deliveryBoy.model
'use strict';
var mongoose = require('bluebird').promisifyAll(require('mongoose'));
var Schema = mongoose.Schema;
var DeliveryBoySchema = new Schema({
name: String,
college: {type:String},
password: {type: String, required: true, select: false},
lat:{type: String},
long:{type:String}
});
//attach a hook to be triggered every time you modify the document
//has to be inserted before the mongoose model is created !!!
//with !!!ATTENTION!!! update method using $set
//for example DeliveryBoy.update({_id:'blah'}, {$set: {long: 1, lat: 0}});
DeliveryBoySchema.post('update', function(){
var update = this._update;
if (update.$set && (update.$set.lat || update.$set.long)){
try{
var updatedObjectId = this._conditions._id; //will serve as a room
var newLoc = {
lat: update.$set.lat,
long: update.$set.long
}
//now emit the event using nodejs event emitter
require('../../components/app.events').emit('updateLoc', {roomId: updatedObjectId, newLoc: newLoc});
}
}
});
module.exports = mongoose.model('DeliveryBoy', DeliveryBoySchema);
//this is the component which implement socket specifically for delivery boy model
//it is called (register method) from general components/socket module
exports.register = function(socket){
AppEvents.on('updateLoc', function(socket){
return function(info){
socket.to(info.roomId).emit('newLocation', info.newLoc);
}
});
}
还有一件事,就是如何从REST API更新数据库
app.put('/update/:gameId', function(req, res){
DeliveryBoy.update({_id: req.params.gameId}, {$set: req.body}, function(err){
res.send(200); //of course this needs to be handled properly, but i am too tired after typing all these
//you owe me couple beers dude
});
});
P.S 代码有点混乱,但您应该能够做出相应的改进。如果有任何问题,请告诉我。但基本概念应该是明确的
答案 1 :(得分:0)
解决方案1并不好,只是因为您的服务器会膨胀并且无法立即响应。忘了这个:)简单地说,首次应用程序加载时,应该只从服务器查询一次该位置。
你可能会认为送货员是一个游戏。假设为了简单起见,只有1名玩家和几名观众。玩家是触发更新的人。观众只能跟踪变化。基本上玩家和观众都在同一个房间,这意味着他们只有在发生变化时才应该更新。
简单地说,关键是选择正确的沟通渠道。我个人会用redis来存储位置,创建订阅频道并通过频道向套接字发布更新。更新位置后,您将持续更新redis中的位置,将更改发布到通道(通过队列),通过订阅使用更改并通过套接字将更新传递给所有侦听客户端。 为何选择redis? 1.适用于分布式系统(可扩展)2。PUB / SUB是一个队列,无需为了同步而获得癌症3. PUB / SUB是持久的4.实际上比纯数据库解决方案更快(与MongoDB相比)