发出Socket.io事件时保存到MongoDB

时间:2014-10-17 16:45:35

标签: javascript ajax angularjs mongodb socket.io

我正在使用MEAN堆栈和Socket.io从实时Instagram API中提取图像。一切都很好,但我现在想开始将图像数据保存到MongoDB数据库,所以我有一个来自位置的图像“历史”(而不是简单的最新照片)。 下面是我到目前为止的相关(工作)代码:

节点服务器端代码,用于处理来自Instagram API的新照片更新并将事件发送到Angular控制器:

// for each new post Instagram sends the data
app.post('/callback', function(req, res) {
    var data = req.body;

    // grab the object_id (as geo_id) of the subscription and send as an argument to the client side
    data.forEach(function(data) {
        var geo_id = data.object_id;
        sendUpdate(geo_id);
    });
    res.end();
});

// send the url with the geo_id to the client side
// to do the ajax call
function sendUpdate(geo_id) {
    io.sockets.emit('newImage', { geo_id: geo_id });
}

收到'newImage'事件时的角度控制器代码:

socket.on('newImage', function(geo_id) {
    // pass geo_id into Instagram API call
    Instagram.get(geo_id).success(function(response) {
        instagramSuccess(response.geo_id, response);
    });

    // Instagram API callback
    var instagramSuccess = function(scope,res) {
        if (res.meta.code !== 200) {
            scope.error = res.meta.error_type + ' | ' + res.meta.error_message;
            return;
        }
        if (res.data.length > 0) {
            $scope.items = res.data;
        } else {
            scope.error = "This location has returned no results";
        }
    };
});

Angular工厂处理对Instagram API的调用:

angular.module('InstaFactory', []).factory('Instagram', function($http) {
    var base = "https://api.instagram.com/v1";
    var client_id = 'MY-CLIENT-ID';

    return {
        'get': function(geo_id) {
            var request = '/geographies/' + geo_id.geo_id + '/media/recent?client_id=' + client_id;
            var url = base + request;
            var config = {
                'params': {
                    'callback': 'JSON_CALLBACK'
                }
            };
            return $http.jsonp(url, config);
        }
    };

});

我还有以下Angular Controller,它目前从我的Stadia mongoDB模型中获取每个位置的详细信息。这个模型还包含一个(现在为空)'照片'数组,我希望每次从Instagram收到它们时都会推送照片详细信息(网址,用户名,用户个人资料网址等):

angular.module('StadiaFactory', []).factory('Stadia', function($http) {
    var base = "http://localhost:6060/api/stadia/";

    return {
        'get': function(id) {
            var request = id;
            var url = base + request;
            var config = {
                'params': {
                    'callback': 'JSON_CALLBACK'
                }
            };
            return $http.jsonp(url, config);
        }
    };

});

这是我感到困惑的地方。我在哪里发出PUT请求到我的Stadia API并且我的Stadia API的这个Node路由看起来合理吗?注意:我省略了我的GET路线,它完美无缺。 PUT只是把我扔了一圈:

// add photos to stadium photos array
app.put('/api/stadia/:stadium_id', function(req, res) {

    // use mongoose to get and update stadium
    Stadium.findByIdAndUpdate(req.params.stadium_id,
        {$push: {"photos": {img: ?, link: ?, username: ?, profile_picture: ?}}},
        {safe: true, upsert: true},
        function(err, stadium) {

        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        res.jsonp(stadium); // return stadium in JSON format
    });
});

1 个答案:

答案 0 :(得分:1)

目前的结构存在一些问题。

调用callback路由时,可能会有N个对象,您正在触发套接字事件并检索您地理位置的所有最后照片每一次。因此,假设您将有3个新对象,您将调用3次相同的数据来获取相同的数据,当您拥有sockets的强大功能时会有点损失。

如果您尝试从客户端获取对象数据并PUT将其发送到服务器,也可能会出现问题,因为您的所有客户端都可能收到套接字,并且最终可能会出现重复项,更不用说这是一个不多的流量,这将燃烧你的配额API限制,在客户端也不安全,因为每个人都可以看到你的密钥。


对我来说,一个让工作变得有效的好方法(即使我真的不知道你的:stadium_id param代表什么)就是直接在服务器端获取你想要的信息{{1使用 request 模块。

您应该只获取图片,因为您可以检索很多您可能不想获得的内容,例如callbackuserstags。所以你必须听取videos个对象,而不是其他任何东西。

你可以这样:

image

然后在您的客户端中,您只需要在var request = require('request'); var CLIENT_ID = 'yourId'; function newImage(data) { io.sockets.emit('newImage', data); } app.post('/callback', function (req, res) { //loop in all the new objects req.body.forEach(function (data) { if (data.type !== 'image') { return ; } //BTW I think you should try with the id property instead of object_id request('https://api.instagram.com/v1/media/' + data.object_id + '?access_token=' + CLIENT_ID, function (error, response, body) { if (error) { return ; } //Here we have one JSON object with all the info about the image var image = JSON.parse(body); //Save the new object to your DB. (replace the STADIUM_ID) Stadium.findByIdAndUpdate(STADIUM_ID, { $push: {'photos': { img: image.images.standard_resolution.url, link: image.link, username: image.user.username, profile_picture: image.user.profile_picture }}}, { safe: true, upsert: true }); //Send a socket to your client with the new image newImage({ id: image.id, img: image.images.standard_resolution.url, link: image.link, username: image.user.username, profile: image.user.profile_picture }); } }); res.end(); }); 中推送newImage套接字事件中收到的新图像。