2016-01-06 61 views
0

我正在製作anroid應用程序並使用express作爲後端。 這是我快遞男孩架構在mongodb中更改客戶端時更新位置

var DeliveryBoySchema = new Schema({ 

    name: String, 
    college: {type:String}, 
    password: {type: String, required: true, select: false}, 
    lat:{type: String}, 
    long:{type:String} 

}); 

當送貨員改變它的位置,它就會在MongoDB的更新。 因此,查看此送貨員的用戶(即客戶)正在跟蹤他的位置。我發現有兩種方法可以做到這一點:

。客戶端每5秒調用一次api並獲取送貨員的當前位置。

。我發現了另一個有趣的方法來做到這一點,即使用套接字。

我不是很清楚它的功能。當數據庫發生更改並且用戶看到當前位置時,我遇到了如何更新客戶端的問題。

回答

0

解決方案1不好,只是因爲您的服務器會臃腫,無法及時響應。忘掉這個:)簡單地說,應該從你的服務器只查詢一次位置,第一次加載應用程序。

你可能會認爲送貨員是一個遊戲。假設爲了簡單起見,只有一個玩家和幾個觀衆。玩家是觸發更新位置的玩家。觀衆只能跟蹤更改。本質上,玩家和觀衆在同一個房間裏,這意味着他們,只有在發生變化時才應該更新他們。

  • 但從玩家角度,這是很簡單的,他是唯一一個誰可以影響的位置,可以同時向服務器更新送外賣的位置和改變你的觀點立場。這裏沒有問題。每當你的玩家改變送貨員的位置時,你都必須堅持存儲更新。
  • 從觀衆的角度來看。每當位置更新發生在數據存儲器中時,您需要通知連接到房間的每個人關於位置的變化。有很多方法可以解決這個問題。但最有可能,你將不得不使用一個插座或其他方式(除了一些XMPP客戶端解決方案,這要複雜得多)

簡單地說,關鍵是要選對通信信道。就我個人而言,我會使用redis來存儲位置,創建訂閱頻道並通過頻道向套接字發佈更新。一旦位置更新,您將持續更新redis中的位置,將更改發佈到頻道(通過隊列),通過訂閱消費更改,並通過套接字將更新傳遞給所有偵聽客戶端。 爲什麼redis? 1.適用於分佈式系統(可擴展)2. PUB/SUB是一個隊列,無需獲得試圖同步的癌症3.PUB/SUB持久4.實際上比純數據庫解決方案(與MongoDB相比)更快

+0

其實,我幾乎完成了我的應用程序。這件事剩下了。如果你告訴我如何將它與mongodb和node結合使用會很棒,js – Nkav

+0

有一個用於該https://github.com/NodeRedis/node_redis的庫 – Yerken

+0

我希望將它與mongodb和node js一起使用,找到解決辦法。 – Nkav

3

根據OP的要求,僅使用mongoose,nodeJSsocket進行編碼。實際執行並不一定完全相同,但以下內容應提供有關如何處理和填補缺失差距的總體思路。爲了方便起見,我將僅使用ES6功能。

nodeJS版本4.2.2,socket.io 1.3。5,貓鼬版4.1.2,表達4.13.3

  1. 創建一個Socket - 服務器端

//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(){ 
     
    \t var update = this._update; 
     
    \t if (update.$set && (update.$set.lat || update.$set.long)){ 
     
    \t \t try{ 
     
    \t \t \t var updatedObjectId = this._conditions._id; //will serve as a room 
     
          var newLoc = { 
     
           lat: update.$set.lat, 
     
           long: update.$set.long 
     
          } 
     
    \t \t \t //now emit the event using nodejs event emitter 
     
    
     
          require('../../components/app.events').emit('updateLoc', {roomId: updatedObjectId, newLoc: newLoc}); 
     
    \t \t } 
     
    \t } 
     
    }); 
     
    
     
    module.exports = mongoose.model('DeliveryBoy', DeliveryBoySchema);

  • 插槽監聽器DeliveryBoy
  • //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); 
     
        } 
     
        }); 
     
    }

  • 現在你只需要連接到基於該deliveryboy ID從客戶端的房間,並使用來自客戶端的消息,並更新你的視圖相應
  • 還有一件事,你這是怎麼從你的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該代碼有點麻煩,但你應該能夠做出相應的改進。如果有任何問題讓我知道。但基本的概念應該清楚

    +0

    Thnaks很多人! :) – Nkav