简体   繁体   中英

Angular + socketio don't work?

Currently I'm trying to implement a real-time content with socket.io and angular.js, and as far as I concern I did everything correct, but the real-time doesnt work. Maybe I miss out anything important.

I will write a scenario of how its supposed to work. Basically a user write a content and then post the value to the server. In home.html, the content supposed to be real time(I have put everything below including home.html).

Here's the code

server.js

var express     = require('express');
var app         = express();
var morgan      = require('morgan');
var mongoose    = require('mongoose');
var bodyParser  = require('body-parser');
var path        = require('path');
var config      = require('./config');

// REAL TIME WORK
var http        = require('http').Server(app);
var io          = require('socket.io')(http);

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(function(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
    next();
});

// log our request to our terminal
app.use(morgan('dev'));

// Connect to our database using mongoose
mongoose.connect(config.database, function(err) {
    if(err) {
        console.log("Connection to a mongodb database has failed");
    } else {
        console.log("Connected to a database");
    }
});


// set our static files to a designated location
app.use(express.static(__dirname + '/public'));

var apiRouter = require('./app/routes/api') (app, express, io);
app.use('/api', apiRouter);

// registered before your api routes.
app.get('*', function(req, res) {
    res.sendFile(path.join(__dirname + '/public/app/views/index.html'));
});

http.listen(config.port, function(err) {
    if(err) {
        console.log("There's an error connecting the app to port" + config.port);
    } else {
        console.log("App is listening on port " + config.port);
    }
});

api.js

module.exports = function(app, express, io) {

    // creating our first router
    var apiRouter = express.Router();

    // signup a user
    var createStory = function(req, res) {

        var story = new Story({
            user: req.decoded.id,
            content: req.body.content
        });

        story.save(function(err) {

            if(err) {
                res.send(err);
                return;
            }

            io.emit('story', req.body.content);
            res.json({ message: 'Story has been created!'});

        });
    };

    apiRouter.route('/')

        .post(createStory)


        .get(function(req, res) {

            Story.find({ user: req.decoded.id }, function(err, story) {
                if(err) {
                    res.send(err);
                    return;
                }

                res.json(story);
            });


        });

service.js

angular.module('storyService', [])


.factory('Story', function($http, $window) {

    // get all approach
    var storyFactory = {};

    var generateReq = function(method, url, data) {
            var req = {
              method: method,
              url: url,
              headers: {
                'x-access-token': $window.localStorage.getItem('token')
              },
              cache: false
            }

            if(method === 'POST') {
                req.data = data;
            }
            return req;
        };

    storyFactory.all = function() {
        return $http(generateReq('GET', '/api/'));
    };


    storyFactory.create = function(storyData) {
        return $http(generateReq('POST', '/api/', storyData));
    };

    storyFactory.getSingleStory = function(user_name, story_id) {
        return $http(generateReq('GET', '/api/' + user_name + '/' + story_id));
    };

    storyFactory.allStories = function() {
        return $http(generateReq('GET', '/api/all_stories'));
    };

    return storyFactory;

})


.factory('socketio', ['$rootScope', function ($rootScope) {

        var socket = io.connect();
        return {
            on: function (eventName, callback) {
                socket.on(eventName, function () {
                    var args = arguments;
                    $rootScope.$apply(function () {
                        callback.apply(socket, args);
                    });
                });
            },
            emit: function (eventName, data, callback) {
                socket.emit(eventName, data, function () {
                    var args = arguments;
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback.apply(socket, args);
                        }
                    });
                });
            }
        };
    }]);

controller.js

angular.module('storyCtrl', ['storyService'])


.controller('StoryController', function(Story, $routeParams, $scope, socketio) {

    var vm = this;

    Story.all()
    .success(function(data) {
        $scope.stories = data;
    });


    Story.getSingleStory($routeParams.user_name, $routeParams.story_id)
    .success(function(data) {
        $scope.storyData = data;
    });

    vm.createStory = function() {


        vm.message = '';

        Story.create(vm.storyData) 
        .success(function(data) {


                // clear the form
                vm.storyData = {}
                vm.message = data.message;

                socketio.on('story', function () {
                    $scope.stories.push(data);
                });

            });
    };

});

index.html

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User Diary</title>


    <base href="/">

    <!-- CSS  -->
    <!-- load bootstrap from CDN and custom CSS -->
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootswatch/3.3.1/paper/bootstrap.min.css">

    <!-- load angular and angular-route via CDN -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-route.js"></script>

    <script src="/socket.io/socket.io.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.js"></script>

    <!-- directives -->



    <!--controllers -->

    <script src="app/controllers/storyCtrl.js"></script>
    <script src="app/services/storyService.js"></script>


    <!-- main Angular app files -->
    <script src="app/app.routes.js"></script>
    <script src="app/app.js"></script>


</head>


<body ng-app="userApp">


<main class="container">

    <!-- ANGULAR VIEWS -->
    <div ng-view></div>
</main>



</body>
</html>

home.html

<div class="panel-body" ng-repeat="story in stories | reverse" >
    <ul class="list-group">
        <li class="list-group-item">
            <div class="row">
                <div class="col-xs-10 col-md-11">
                    <div>
                        <div class="mic-info">
                            {{ story.createdAt | date:'MMM d, yyyy' }}
                        </div>
                    </div>
                    <div class="comment-text">
                        <h4>{{ story.content }}</h4>
                    </div>
                </div>
            </div>
        </li>
    </ul>
</div>

I know its huge, the reason why I'm posting it all is because I don't want to miss out on anything.

I'm really new to this whole socket.io + angular.js, if you have any opinion that could teach me something about socket.io + angular.js that would mean alot to me :)

Following on from the comments.

  1. An event listener socketio.on(..) only needs to be created once. It will receive all future events until it is removed. Also don't mix vm and $scope

     angular.module('storyCtrl', ['storyService']) .controller('StoryController', function(Story, $routeParams, socketio) { var vm = this; vm.stories = []; Story.all() .success(function(data) { vm.stories = data; }); Story.getSingleStory($routeParams.user_name, $routeParams.story_id) .success(function(data) { vm.storyData = data; }); vm.createStory = function() { vm.message = ''; Story.create(vm.storyData) .success(function(data) { // clear the form vm.storyData = {} vm.message = data.message; }); }; socketio.on('story', function (data) { vm.stories.push(data); }); }); 

    Create the controller like ng-controller="StoryController as StoryCtrl" and repeat with ng-repeat="story in StoryCtrl.stories"

  2. Your server side emit only responds with the post content when it seems it should return an object with at least content and createdAt properties

     // signup a user var createStory = function(req, res) { var story = new Story({ user: req.decoded.id, content: req.body.content }); story.save(function(err) { if(err) { res.send(err); return; } io.emit('story', { user: req.decoded.id, createdAt: new Date(), content: req.body.content }); // you might be able to do instead // io.emit('story', story.toObject()) res.json({ message: 'Story has been created!'}); }); }; 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM