3

AngularJS で作成したこの基本的な CRUD Todo アプリがあります。次に、Socket.IO を使ってこれをリアルタイムの Web アプリにしたいと考えました。ただし、正しく動作させるにはいくつか問題があります。

セットアップ: Yeoman (bower+grunt) AngularJS RequireJS NodeJS + MongoDB Socket.IO

「うなり声サーバー」は localhost:9000 で実行されますが、NodeJS/MongoDB/Socket.IO サーバーは localhost:4711 で実行されます。

現時点で Socket.IO で機能するのは、todo の作成と削除ですが、todo を更新する方法がわかりません。とても簡単だと思ったもの。

コーデはこちら。

ソケット.js:

var io = require('socket.io');

exports.initialize = function(server) {
  io = io.listen(server);
  io.sockets.on('connection', function(socket) {
    socket.on('message', function(message) {
      message = JSON.parse(message);
      socket.get('deletedTodo', function(err, nickname) {
        socket.broadcast.send(JSON.stringify(message));
        socket.send(JSON.stringify(message));
      });
    });
    socket.on('delete_todo', function(data) {
      socket.set('deletedTodo', data.title, function() {
        socket.emit('todo_delete', data);

        socket.broadcast.emit('todoDeleted', data);
      });
    });
    socket.on('update_todo', function(data) {
      socket.broadcast.emit('todoUpdated', data);
    })
  });
}

そして、これが私のクライアント側のコードです。

Services.js:

/*global define*/
define(['angular'], function(angular) {
 'use strict';

 return angular.module('services', [])
   .factory('Todo', function($resource) {
     //var baseUrl = 'http://designit-todo.eu01.aws.af.cm/api/todos/:id';
     var baseUrl = 'http://localhost:port/api/todos/:id';
     return $resource(baseUrl,
       {port: ':4711', id: '@_id'}, {
       'update': {method:'PUT'},
       'delete': {method:'DELETE', isArray: true}
     });
   })
   .factory('socket', function($rootScope) {
     var socket = io.connect('http://localhost:4711');
     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);
             }
           });
         });
       },
       send: function(eventName, data, callback) {
         socket.send(eventName, data, function() {
           var args = arguments;
           $rootScope.$apply(function() {
             if (callback) {
               callback.apply(socket, args);
             }
           });
         });
       }
     }
   });
});

Controllers.js:

/*global define*/
define(['angular', 'services/services'], function(angular) {
'use strict';

return angular.module('controllers', ['services'])
.controller('Todos', ['$scope', '$resource', 'Todo', '$location', 'socket',        function($scope, $resource, Todo, $location, socket) {
  // Grab all todos.
  $scope.todos = Todo.query();

  socket.on('message', function(data) {
    // Grab all todos when new added via socket.
    $scope.todos = Todo.query();

    $scope.todos.push(data);
  });

  // Complete/update todo.
  $scope.todoCompleted = function(todo) {
    todo.$update();
    socket.emit('update_todo', todo);
  }
  socket.on('todoUpdated', function(todo) {
    // Update on all connected clients.
    console.log(todo);
  });

  $scope.removeTodo = function(todo) {
    var index = $scope.todos.indexOf(todo);
    socket.emit("delete_todo", JSON.stringify(index));
    $scope.todos.splice(index, 1);
    todo.$remove();
  }
  socket.on('todoDeleted', function(index) {
    $scope.todos.splice(index, 1);
  });
}])
.controller('Single', ['$scope', '$resource', '$routeParams', 'Todo', '$timeout', '$location', function($scope, $resource, $routeParams, Todo, $timeout, $location) {
  // Grab just a single todo
  $scope.todo = Todo.get({ id: $routeParams.id });
  // Throttle the update PUT request
  var saveTimeout;
  $scope.save = function() {
    $timeout.cancel(saveTimeout);
    saveTimeout = $timeout(function() {
      // Save the todo and then update the scope
      $scope.todo.$update(function(updated_todo) {
        $scope.todo = updated_todo;
      });
    }, 1000);
  };
}])
.controller('Add', ['$scope', '$resource', 'Todo', '$location', 'socket', function($scope, $resource, Todo, $location, socket) {
  $scope.todo = new Todo({});

  $scope.save = function() {
    if ($scope.todo.title) {
      $scope.todo.$save(function(data) {
        console.log(data);
        socket.send(JSON.stringify(data));
        $location.path('/');
      });
    }
  }
}]);
});

だから私の問題は、このコードの中にあります:

// Complete/update todo.
$scope.todoCompleted = function(todo) {
  todo.$update();
  socket.emit('update_todo', todo);
}
socket.on('todoUpdated', function(todo) {
  // Update on all connected clients.
  console.log(todo);
});

console.log(todo) すると todo が取得されますが、"todo.$update" を実行できます。私も次のようなことを試しました:

  socket.on('todoUpdated', function(todo) {
    var thisTodo = Todo.get({id: todo._id});
    console.log(thisTodo);
  });

しかし、 thisTodo.$update() を実行しようとするとすぐにエラーが発生します:

PUT http://localhost:4711/api/todos 404 (Not Found) :4711/api/todos:1

私は何を間違っていますか?コード内で何か間違ったことをしている場合は、修正してください。私はまだ AngularJS と Socket.IO にかなり慣れていません。

4

1 に答える 1